-
Notifications
You must be signed in to change notification settings - Fork 23
Open
Description
Hi,
I've been digging into why surrealdb-migrations was adding about a minute to my startup process.
2025-06-02T01:20:37.985151Z DEBUG surrealdb_migrations::apply: stmt: [Define(Table(DefineTableStatement { id: None, name: Ident("item_dependencies"), drop: false, full: true, view: None, permissions: Permissions { select: None, create: None, update: None, delete: None }, changefeed: None, comment: None, if_not_exists: false, kind: Relation(Relation { from: Some(Record([Table("workshop_items")])), to: Some(Record([Table("workshop_items")])), enforced: false }), overwrite: true, cache_fields_ts: 00000000-0000-0000-0000-000000000000, cache_events_ts: 00000000-0000-0000-0000-000000000000, cache_tables_ts: 00000000-0000-0000-0000-000000000000, cache_indexes_ts: 00000000-0000-0000-0000-000000000000 })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("in"))]), what: Ident("item_dependencies"), flex: false, kind: Some(Record([Table("workshop_items")])), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("out"))]), what: Ident("item_dependencies"), flex: false, kind: Some(Record([Table("workshop_items")])), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Index(DefineIndexStatement { name: Ident("dep_out"), what: Ident("item_dependencies"), cols: Idioms([Idiom([Field(Ident("out"))])]), index: Idx, comment: None, if_not_exists: false, overwrite: true, concurrently: false })), Define(Table(DefineTableStatement { id: None, name: Ident("script_migration"), drop: false, full: true, view: None, permissions: Permissions { select: Full, create: None, update: None, delete: None }, changefeed: None, comment: None, if_not_exists: false, kind: Normal, overwrite: true, cache_fields_ts: 00000000-0000-0000-0000-000000000000, cache_events_ts: 00000000-0000-0000-0000-000000000000, cache_tables_ts: 00000000-0000-0000-0000-000000000000, cache_indexes_ts: 00000000-0000-0000-0000-000000000000 })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("script_name"))]), what: Ident("script_migration"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("executed_at"))]), what: Ident("script_migration"), flex: false, kind: Some(Datetime), readonly: true, value: Some(Function(Normal("time::now", []))), assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Table(DefineTableStatement { id: None, name: Ident("tags"), drop: false, full: true, view: None, permissions: Permissions { select: None, create: None, update: None, delete: None }, changefeed: None, comment: None, if_not_exists: false, kind: Normal, overwrite: true, cache_fields_ts: 00000000-0000-0000-0000-000000000000, cache_events_ts: 00000000-0000-0000-0000-000000000000, cache_tables_ts: 00000000-0000-0000-0000-000000000000, cache_indexes_ts: 00000000-0000-0000-0000-000000000000 })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("app_id"))]), what: Ident("tags"), flex: false, kind: Some(Int), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("display_name"))]), what: Ident("tags"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("id"))]), what: Ident("tags"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Index(DefineIndexStatement { name: Ident("field_app_id_tag"), what: Ident("tags"), cols: Idioms([Idiom([Field(Ident("app_id"))]), Idiom([Field(Ident("display_name"))])]), index: Idx, comment: None, if_not_exists: true, overwrite: false, concurrently: false })), Define(Table(DefineTableStatement { id: None, name: Ident("workshop_items"), drop: false, full: true, view: None, permissions: Permissions { select: None, create: None, update: None, delete: None }, changefeed: None, comment: None, if_not_exists: false, kind: Normal, overwrite: true, cache_fields_ts: 00000000-0000-0000-0000-000000000000, cache_events_ts: 00000000-0000-0000-0000-000000000000, cache_tables_ts: 00000000-0000-0000-0000-000000000000, cache_indexes_ts: 00000000-0000-0000-0000-000000000000 })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("appid"))]), what: Ident("workshop_items"), flex: false, kind: Some(Int), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("preview_url"))]), what: Ident("workshop_items"), flex: false, kind: Some(Option(String)), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("id"))]), what: Ident("workshop_items"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("author"))]), what: Ident("workshop_items"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("description"))]), what: Ident("workshop_items"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("languages"))]), what: Ident("workshop_items"), flex: false, kind: Some(Set(Int, None)), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("last_updated"))]), what: Ident("workshop_items"), flex: false, kind: Some(Int), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("tags"))]), what: Ident("workshop_items"), flex: false, kind: Some(Set(Record([Table("tags")]), None)), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("tags")), All]), what: Ident("workshop_items"), flex: false, kind: Some(Record([Table("tags")])), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("title"))]), what: Ident("workshop_items"), flex: false, kind: Some(String), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Field(DefineFieldStatement { name: Idiom([Field(Ident("score"))]), what: Ident("workshop_items"), flex: false, kind: Some(Float), readonly: false, value: None, assert: None, default: None, permissions: Permissions { select: Full, create: Full, update: Full, delete: Full }, comment: None, if_not_exists: false, overwrite: true, reference: None, default_always: false })), Define(Index(DefineIndexStatement { name: Ident("item_updated"), what: Ident("workshop_items"), cols: Idioms([Idiom([Field(Ident("last_updated"))])]), index: Idx, comment: None, if_not_exists: false, overwrite: true, concurrently: false })), Define(Index(DefineIndexStatement { name: Ident("item_language"), what: Ident("workshop_items"), cols: Idioms([Idiom([Field(Ident("languages"))])]), index: Idx, comment: None, if_not_exists: false, overwrite: true, concurrently: false })), Define(Index(DefineIndexStatement { name: Ident("item_title"), what: Ident("workshop_items"), cols: Idioms([Idiom([Field(Ident("title"))])]), index: Idx, comment: None, if_not_exists: false, overwrite: true, concurrently: false })), Define(Index(DefineIndexStatement { name: Ident("item_score"), what: Ident("workshop_items"), cols: Idioms([Idiom([Field(Ident("score"))])]), index: Idx, comment: None, if_not_exists: false, overwrite: true, concurrently: false }))], action: Commit
2025-06-02T01:21:33.945504Z DEBUG surrealdb_migrations::apply: surrealdb-migrations/src/apply.rs:485
Subject: [PATCH] stuff
---
Index: src/apply.rs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/apply.rs b/src/apply.rs
--- a/src/apply.rs (revision 4820eea96ae1af98e50dfc09c05344492ab15c6c)
+++ b/src/apply.rs (revision 278d8df0046c62d1c1e70ed9dc18ea5ecd1a13e2)
@@ -476,8 +476,10 @@
.collect::<Vec<_>>();
let transaction_action = get_transaction_action(dry_run);
+ debug!("{}:{}", file!(), line!());
+ debug!("stmt: {statements:?}, action: {transaction_action:?}");
surrealdb::apply_in_transaction(client, statements, transaction_action).await?;
-
+ debug!("{}:{}", file!(), line!());
if !current_definition.schemas.is_empty() {
has_applied_schemas = true;
}
This isn't a particularly large database either, at about 100 MiB & about 75k rows.
Anyway, the fix for this is pretty straightforward:
Subject: [PATCH] fix: Running migrations unnecessarily
---
Index: src/apply.rs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/apply.rs b/src/apply.rs
--- a/src/apply.rs (revision 278d8df0046c62d1c1e70ed9dc18ea5ecd1a13e2)
+++ b/src/apply.rs (revision 3a9b2937439f827d0c186e5621134f2fcc213d7b)
@@ -436,7 +436,7 @@
) -> Result<()> {
let mut has_applied_schemas = false;
let mut has_applied_events = false;
- let has_applied_migrations = !&migration_files_to_execute.is_empty();
+ let pending_migrations = !migration_files_to_execute.is_empty();
let mut current_definition: SchemaMigrationDefinition = Default::default();
if use_migration_definitions {
@@ -453,6 +453,7 @@
}?;
if !has_applied_migrations {
+ if pending_migrations {
let schemas_statements = current_definition.schemas.to_string();
let events_statements = current_definition.events.to_string();
Please don't hesitate to pinch that patch; otherwise, I can submit it as a pull request. That said, I would very much like to see this as an opportunity for adding some form of observability into this crate, given that it won't always be possible to debug this problem like I have.
Personally, I'm a big fan of working within the tracing ecosystem, however, something as simple as descriptive logging would work as well.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels