refactor(database): split monolithic database.py into modular package#43
Conversation
…ttings - Implemented PlanOperationsMixin for managing plans and tasks, including creation, retrieval, updating, and deletion. - Added PostprocessOperationsMixin to handle postprocess job lifecycle, including job creation, status updates, and metrics tracking. - Introduced ProjectOperationsMixin for project management, including project creation, retrieval, and linking chats to projects. - Created SettingsOperationsMixin for managing user preferences, volume metadata, memory configuration, and MCP server operations. - Each mixin includes methods for interacting with the database using SQLModel and handling various operations related to their respective domains.
There was a problem hiding this comment.
Pull request overview
This PR refactors Suzent’s persistence layer by replacing the monolithic src/suzent/database.py with a modular src/suzent/database/ package composed of focused mixins and a facade, while preserving the public import surface via src/suzent/database/__init__.py.
Changes:
- Split the database layer into separate modules (
models,migrations,chats,projects,plans,postprocess,cron,settings) and composed them via afacade.ChatDatabase. - Kept the external API stable (
from suzent.database import ChatDatabase, get_database, ...) via the package__init__.py. - Refactored/centralized repeated patterns (e.g., shared chat filters helper; some logic moved from Python filtering to SQL predicates).
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/suzent/database/init.py | Defines the preserved public API surface and global get_database() singleton. |
| src/suzent/database/base.py | Provides engine/session setup and startup-time hooks (create_all + migrations + one-time migrations). |
| src/suzent/database/chats.py | Chat CRUD/listing + snapshot/finalize lifecycle + filtering helpers. |
| src/suzent/database/cron.py | Cron job CRUD and cron run history persistence. |
| src/suzent/database/facade.py | Composes the database facade class from the mixins. |
| src/suzent/database/migrations.py | Contains schema migrations and legacy data/directory migration helpers. |
| src/suzent/database/models.py | Centralizes SQLModel table definitions and query helper(s). |
| src/suzent/database/plans.py | Plan/task persistence and retrieval behavior. |
| src/suzent/database/postprocess.py | Postprocess job lifecycle, step status, and retry logic. |
| src/suzent/database/projects.py | Project CRUD, default/social project bootstrapping, and subagent/project utilities. |
| src/suzent/database/settings.py | User-config-backed settings, volume metadata upserts, MCP server persistence, and config blob/secret helpers. |
| src/suzent/database.py | Removes the previous monolithic module in favor of the new package. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def delete_api_key(self, key: str) -> bool: | ||
| """Delete a config blob or secret outside the runtime database.""" | ||
| if key.startswith("_"): | ||
| from suzent.core.user_config import UserConfigStore | ||
|
|
||
| UserConfigStore().delete_config_blob(key) | ||
| else: | ||
| from suzent.core.secrets import get_secret_manager | ||
|
|
||
| get_secret_manager().delete(key) |
| job.status = ( | ||
| PostProcessStatus.SUCCESS | ||
| if outcome == PostProcessOutcome.SUCCESS | ||
| else PostProcessStatus.FAILED | ||
| ) |
| def delete_api_key(self, key: str) -> bool: | ||
| """Delete a config blob or secret outside the runtime database.""" | ||
| if key.startswith("_"): | ||
| from suzent.core.user_config import UserConfigStore | ||
|
|
||
| UserConfigStore().delete_config_blob(key) | ||
| else: | ||
| from suzent.core.secrets import get_secret_manager | ||
|
|
||
| get_secret_manager().delete(key) |
| job.status = ( | ||
| PostProcessStatus.SUCCESS | ||
| if outcome == PostProcessOutcome.SUCCESS | ||
| else PostProcessStatus.FAILED | ||
| ) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b509b029a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| UserConfigStore().delete_config_blob(key) | ||
| else: | ||
| from suzent.core.secrets import get_secret_manager | ||
|
|
There was a problem hiding this comment.
Preserve delete_api_key's success return
This method is still annotated as returning bool and previously returned True after either deletion path, but the refactor drops the success return. Any caller that uses delete_api_key(...) to decide whether deletion succeeded will now treat successful deletes as falsy (None), even though the key/config blob was removed.
Useful? React with 👍 / 👎.
…ale status mapping - delete_api_key() was missing `return True` after the refactor, causing callers to receive None instead of a bool on success - finalize_postprocess_job() was mapping skipped_stale outcome to FAILED status; now maps it to SKIPPED_STALE so status and outcome stay consistent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
src/suzent/database.pywith asrc/suzent/database/package split by responsibility:models,migrations,chats,projects,plans,postprocess,cron,settings, and afacadethat composes them allsuzent.databasecontinue to work via__init__.py_apply_chat_filters,_get_job_by_job_id, and_sort_plan_taskshelpers to eliminate copy-pasted patterns; pushedheartbeat_enabledand subagent filters from Python to SQL; collapsedset_mcp_server_enabledintoupdate_mcp_server; deduplicatedsave_volume_metadataupsert branchesTest plan
python -c "from suzent.database import ChatDatabase, get_database, generate_chat_title"🤖 Generated with Claude Code