From 0baaeac00a9ad03f1dd4221d31ce43c6208b5fd4 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Thu, 2 Apr 2026 03:01:46 +0800 Subject: [PATCH] fix(api): repair conversation is_deleted removal migration --- ...a95e676f_remove_unused_is_deleted_from_.py | 35 +++++++++++++++++-- api/models/model.py | 14 ++------ .../services/test_conversation_service.py | 1 - 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/api/migrations/versions/2025_11_27_1827-e5d7a95e676f_remove_unused_is_deleted_from_.py b/api/migrations/versions/2025_11_27_1827-e5d7a95e676f_remove_unused_is_deleted_from_.py index a279f7339e4..c77d26fd7e9 100644 --- a/api/migrations/versions/2025_11_27_1827-e5d7a95e676f_remove_unused_is_deleted_from_.py +++ b/api/migrations/versions/2025_11_27_1827-e5d7a95e676f_remove_unused_is_deleted_from_.py @@ -1,8 +1,8 @@ """remove unused is_deleted from conversations Revision ID: e5d7a95e676f -Revises: 288345cd01d1 -Create Date: 2025-11-27 18:27:09.006691 +Revises: 6b5f9f8b1a2c +Create Date: 2026-04-02 00:00:00.000000 """ @@ -10,21 +10,48 @@ import sqlalchemy as sa from alembic import op revision = "e5d7a95e676f" -down_revision = "9d77545f524e" +down_revision = "6b5f9f8b1a2c" branch_labels = None depends_on = None +CONVERSATION_CREATED_AT_INDEX_NAME = "conversation_app_created_at_idx" +CONVERSATION_UPDATED_AT_INDEX_NAME = "conversation_app_updated_at_idx" + + +def _recreate_conversation_indexes(*, use_partial_indexes: bool) -> None: + index_kwargs: dict[str, object] = {"unique": False} + if use_partial_indexes: + index_kwargs["postgresql_where"] = sa.text("is_deleted IS false") + + with op.batch_alter_table("conversations", schema=None) as batch_op: + batch_op.create_index( + CONVERSATION_CREATED_AT_INDEX_NAME, + ["app_id", sa.literal_column("created_at DESC")], + **index_kwargs, + ) + batch_op.create_index( + CONVERSATION_UPDATED_AT_INDEX_NAME, + ["app_id", sa.literal_column("updated_at DESC")], + **index_kwargs, + ) + def upgrade(): conversations = sa.table("conversations", sa.column("is_deleted", sa.Boolean)) op.execute(sa.delete(conversations).where(conversations.c.is_deleted == sa.true())) with op.batch_alter_table("conversations", schema=None) as batch_op: + batch_op.drop_index(CONVERSATION_UPDATED_AT_INDEX_NAME) + batch_op.drop_index(CONVERSATION_CREATED_AT_INDEX_NAME) batch_op.drop_column("is_deleted") + _recreate_conversation_indexes(use_partial_indexes=False) + def downgrade(): with op.batch_alter_table("conversations", schema=None) as batch_op: + batch_op.drop_index(CONVERSATION_UPDATED_AT_INDEX_NAME) + batch_op.drop_index(CONVERSATION_CREATED_AT_INDEX_NAME) batch_op.add_column( sa.Column( "is_deleted", @@ -34,3 +61,5 @@ def downgrade(): nullable=False, ) ) + + _recreate_conversation_indexes(use_partial_indexes=True) diff --git a/api/models/model.py b/api/models/model.py index 07019b23cab..886e45aae46 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -1029,18 +1029,8 @@ class Conversation(Base): __table_args__ = ( sa.PrimaryKeyConstraint("id", name="conversation_pkey"), sa.Index("conversation_app_from_user_idx", "app_id", "from_source", "from_end_user_id"), - sa.Index( - "conversation_app_created_at_idx", - "app_id", - sa.text("created_at DESC"), - postgresql_where=sa.text("is_deleted IS false"), - ), - sa.Index( - "conversation_app_updated_at_idx", - "app_id", - sa.text("updated_at DESC"), - postgresql_where=sa.text("is_deleted IS false"), - ), + sa.Index("conversation_app_created_at_idx", "app_id", sa.text("created_at DESC")), + sa.Index("conversation_app_updated_at_idx", "app_id", sa.text("updated_at DESC")), ) id: Mapped[str] = mapped_column(StringUUID, default=lambda: str(uuid4())) diff --git a/api/tests/test_containers_integration_tests/services/test_conversation_service.py b/api/tests/test_containers_integration_tests/services/test_conversation_service.py index 6180d98b1ef..c72b832af06 100644 --- a/api/tests/test_containers_integration_tests/services/test_conversation_service.py +++ b/api/tests/test_containers_integration_tests/services/test_conversation_service.py @@ -112,7 +112,6 @@ class ConversationServiceIntegrationTestDataFactory: from_end_user_id=user.id if isinstance(user, EndUser) else None, from_account_id=user.id if isinstance(user, Account) else None, dialogue_count=0, - is_deleted=False, ) conversation.inputs = {} if updated_at is not None: