-
Notifications
You must be signed in to change notification settings - Fork 122
Refactor: DynamicSidebar default initialization to use config.toml #1914
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
Refactor: DynamicSidebar default initialization to use config.toml #1914
Conversation
71a8bd6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR moves DynamicSidebar’s default menu initialization out of a historical migration and into runtime bootstrap driven by [sidebar] in config.toml, aiming to make defaults configurable and keep migrations schema-focused.
Changes:
- Initialize default
dynamic_sidebarrows at startup fromconfig.sidebar.default_itemswhen the table is empty. - Add a new migration intended to remove historically inserted default sidebar rows.
- Extend
common::config::Configwith asidebarsection and add sidebar defaults to the repo’s TOML configs.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| jupiter/src/storage/mod.rs | Calls sidebar default initialization during Storage::new() startup. |
| jupiter/src/storage/dynamic_sidebar_storage.rs | Adds init_default_sidebars() that seeds DB rows from SidebarConfig when empty. |
| jupiter/src/migration/mod.rs | Registers the new cleanup migration. |
| jupiter/src/migration/m20260209_064016_remove_default_dynamic_sidebar.rs | New migration that deletes dynamic_sidebar contents (currently unconditional for Postgres). |
| config/config.toml | Adds [sidebar] default_items defaults. |
| config/config-workflow.toml | Adds [sidebar] default_items defaults for workflow config. |
| config/config-test.toml | Adds [sidebar] default_items defaults for test config. |
| common/src/config/mod.rs | Introduces SidebarConfig / SidebarItem and adds Config.sidebar. |
| async fn down(&self, _: &SchemaManager) -> Result<(), DbErr> { | ||
| Ok(()) | ||
| } |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
down() is a no-op for a destructive data migration. In this repo, migrations generally provide a meaningful rollback; if rollback isn’t possible, it’s better to either re-insert the previous default rows (if acceptable) or return an explicit error indicating the migration is irreversible, rather than silently succeeding.
| pub async fn init_default_sidebars(&self, config: &SidebarConfig) -> Result<(), MegaError> { | ||
| let count = dynamic_sidebar::Entity::find() | ||
| .count(self.get_connection()) | ||
| .await?; | ||
| if count > 0 { |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
init_default_sidebars uses a separate COUNT(*) check followed by individual inserts without a transaction/lock. Under concurrent startups (multiple instances), two processes can both observe count=0 and then race inserting, leading to unique constraint violations on public_id (or partial inserts if a later insert fails). Prefer an atomic "insert defaults if table empty" approach (single SQL statement / transaction with proper locking) or conflict-tolerant inserts so startup remains idempotent.
| SidebarItem { | ||
| public_id: "docs".to_string(), | ||
| label: "Docs".to_string(), | ||
| href: "/notes".to_string(), | ||
| visible: true, | ||
| order_index: 2, | ||
| }, |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SidebarConfig::default() seeds an item with public_id = "docs", but the historical migration and the new TOML defaults use public_id = "notes" for the Docs entry. If the [sidebar] config is omitted (or in tests using Config::mock()), this will initialize a different public_id and can break any code/UI that relies on stable IDs. Align the Rust defaults with the TOML/migration IDs.
| # Default sidebar menu items. | ||
| # - Visible = false means the menu is hidden by default. | ||
| # - Order_index controls the display order in the UI. | ||
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says changes here don’t affect old environments, but this PR also adds a migration that deletes all rows from dynamic_sidebar on Postgres, which will make existing DBs empty and therefore re-seeded from these defaults at runtime. Either adjust the migration to avoid wiping existing data, or update this comment to reflect the actual behavior.
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. | |
| # - These defaults are applied to new or empty DBs, and to existing DBs after | |
| # migrations that clear the dynamic_sidebar table. Changing them may affect | |
| # old environments once such a migration has been applied. |
| # Default sidebar menu items. | ||
| # - Visible = false means the menu is hidden by default. | ||
| # - Order_index controls the display order in the UI. | ||
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says changes here don’t affect old environments, but this PR also adds a migration that deletes all rows from dynamic_sidebar on Postgres, which will make existing DBs empty and therefore re-seeded from these defaults at runtime. Either adjust the migration to avoid wiping existing data, or update this comment to reflect the actual behavior.
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. | |
| # - Changes here affect environments whenever the dynamic_sidebar table is empty | |
| # (for example, on new installs or after migrations that clear sidebar data). |
| # Default sidebar menu items. | ||
| # - Visible = false means the menu is hidden by default. | ||
| # - Order_index controls the display order in the UI. | ||
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says changes here don’t affect old environments, but this PR also adds a migration that deletes all rows from dynamic_sidebar on Postgres, which will make existing DBs empty and therefore re-seeded from these defaults at runtime. Either adjust the migration to avoid wiping existing data, or update this comment to reflect the actual behavior.
| # - Changes here do not affect old environments; only new or empty DBs will use these defaults. | |
| # - Note: a Postgres migration clears the `dynamic_sidebar` table on upgrade, | |
| # so existing databases may also be reseeded from these defaults. |
| DatabaseBackend::Postgres => { | ||
| let sql = r#"DELETE FROM dynamic_sidebar;"#; | ||
| manager.get_connection().execute_unprepared(sql).await?; | ||
| } |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This migration unconditionally deletes all rows from dynamic_sidebar on Postgres. Since the table supports user-driven updates (see DynamicSidebarStorage CRUD/sync), applying this in existing environments will wipe any customized sidebar configuration. Consider making the cleanup conditional (e.g., only delete if rows exactly match the legacy hard-coded defaults), or delete only the legacy public_ids, to avoid data loss.
| //! 1. **Schema vs. Data Separation** | ||
| //! - Migrations should only define or modify database **schema** (tables, columns, indexes). | ||
| //! - They should **not** insert default or seed data. | ||
| //! - Default menu data is now managed at **runtime** via a bootstrap method (`DynamicSidebarStorage::bootstrap_sidebar`) that reads from configuration (e.g., `sidebar.default.toml`). | ||
| //! |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The module-level docs mention DynamicSidebarStorage::bootstrap_sidebar and sidebar.default.toml, but the actual runtime initializer added in this PR is init_default_sidebars and it reads from the main config [sidebar] section. Please update these references to match the implementation to avoid misleading future maintainers.
背景 / 历史问题
m20251203_013745_add_dynamic_sidebar.rs中插入了硬编码的默认菜单数据。这样导致:
我们希望遵循基本的约定:
设计思路
移除历史 migration 的默认数据插入:
动态初始化默认菜单:
DynamicSidebarStorage中增加init_default_sidebars方法;config/config.toml读取sidebar.default_items;如果表为空,插入默认菜单,保证幂等性;
Storage 初始化阶段调用该方法,确保新环境启动时自动 bootstrap。
默认菜单更新:
config/config.toml,修改时只需要改配置,不再改 migration。默认 sidebar 改动
Calls和Rust默认项,即字段visible = false;Orion Client(public_id=oc);