Skip to content

refactor(database): split monolithic database.py into modular package#43

Merged
cyzus merged 2 commits into
mainfrom
feat/refactor-database
May 30, 2026
Merged

refactor(database): split monolithic database.py into modular package#43
cyzus merged 2 commits into
mainfrom
feat/refactor-database

Conversation

@cyzus
Copy link
Copy Markdown
Owner

@cyzus cyzus commented May 30, 2026

Summary

  • Replaces the single 3031-line src/suzent/database.py with a src/suzent/database/ package split by responsibility: models, migrations, chats, projects, plans, postprocess, cron, settings, and a facade that composes them all
  • Public API is unchanged — all existing imports from suzent.database continue to work via __init__.py
  • Applied simplification cleanup during refactor: extracted _apply_chat_filters, _get_job_by_job_id, and _sort_plan_tasks helpers to eliminate copy-pasted patterns; pushed heartbeat_enabled and subagent filters from Python to SQL; collapsed set_mcp_server_enabled into update_mcp_server; deduplicated save_volume_metadata upsert branches

Test plan

  • Import smoke test: python -c "from suzent.database import ChatDatabase, get_database, generate_chat_title"
  • Start the app and verify chat list loads, create/delete chat, open a chat with heartbeat enabled
  • Verify subagent chat IDs are returned correctly for a parent chat
  • Verify MCP server enable/disable toggle still works
  • Run existing test suite against the package

🤖 Generated with Claude Code

…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.
Copilot AI review requested due to automatic review settings May 30, 2026 15:16
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 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 a facade.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.

Comment on lines +272 to +281
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)
Comment on lines +160 to +164
job.status = (
PostProcessStatus.SUCCESS
if outcome == PostProcessOutcome.SUCCESS
else PostProcessStatus.FAILED
)
Comment on lines +272 to +281
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)
Comment on lines +160 to +164
job.status = (
PostProcessStatus.SUCCESS
if outcome == PostProcessOutcome.SUCCESS
else PostProcessStatus.FAILED
)
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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>
@cyzus cyzus merged commit d108b57 into main May 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants