mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-30 21:59:46 +02:00
Add thread_id to chat_comments for Electric sync
This commit is contained in:
parent
3ab9cc8485
commit
ac7d84571d
3 changed files with 80 additions and 2 deletions
|
|
@ -0,0 +1,68 @@
|
||||||
|
"""Add thread_id to chat_comments for denormalized Electric subscriptions
|
||||||
|
|
||||||
|
This denormalization allows a single Electric SQL subscription per thread
|
||||||
|
instead of one per message, significantly reducing connection overhead.
|
||||||
|
|
||||||
|
Revision ID: 75
|
||||||
|
Revises: 74
|
||||||
|
"""
|
||||||
|
|
||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
revision: str = "75"
|
||||||
|
down_revision: str | None = "74"
|
||||||
|
branch_labels: str | Sequence[str] | None = None
|
||||||
|
depends_on: str | Sequence[str] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Add thread_id column to chat_comments and backfill from messages."""
|
||||||
|
# Add the column (nullable initially for backfill)
|
||||||
|
op.execute(
|
||||||
|
"""
|
||||||
|
ALTER TABLE chat_comments
|
||||||
|
ADD COLUMN IF NOT EXISTS thread_id INTEGER;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Backfill thread_id from the related message
|
||||||
|
op.execute(
|
||||||
|
"""
|
||||||
|
UPDATE chat_comments c
|
||||||
|
SET thread_id = m.thread_id
|
||||||
|
FROM new_chat_messages m
|
||||||
|
WHERE c.message_id = m.id
|
||||||
|
AND c.thread_id IS NULL;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make it NOT NULL after backfill
|
||||||
|
op.execute(
|
||||||
|
"""
|
||||||
|
ALTER TABLE chat_comments
|
||||||
|
ALTER COLUMN thread_id SET NOT NULL;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add FK constraint
|
||||||
|
op.execute(
|
||||||
|
"""
|
||||||
|
ALTER TABLE chat_comments
|
||||||
|
ADD CONSTRAINT fk_chat_comments_thread_id
|
||||||
|
FOREIGN KEY (thread_id) REFERENCES new_chat_threads(id) ON DELETE CASCADE;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add index for efficient Electric subscriptions by thread
|
||||||
|
op.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_chat_comments_thread_id ON chat_comments(thread_id)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Remove thread_id column from chat_comments."""
|
||||||
|
op.execute("DROP INDEX IF EXISTS idx_chat_comments_thread_id")
|
||||||
|
op.execute("ALTER TABLE chat_comments DROP CONSTRAINT IF EXISTS fk_chat_comments_thread_id")
|
||||||
|
op.execute("ALTER TABLE chat_comments DROP COLUMN IF EXISTS thread_id")
|
||||||
|
|
@ -413,6 +413,13 @@ class ChatComment(BaseModel, TimestampMixin):
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
|
# Denormalized thread_id for efficient Electric SQL subscriptions (one per thread)
|
||||||
|
thread_id = Column(
|
||||||
|
Integer,
|
||||||
|
ForeignKey("new_chat_threads.id", ondelete="CASCADE"),
|
||||||
|
nullable=False,
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
parent_id = Column(
|
parent_id = Column(
|
||||||
Integer,
|
Integer,
|
||||||
ForeignKey("chat_comments.id", ondelete="CASCADE"),
|
ForeignKey("chat_comments.id", ondelete="CASCADE"),
|
||||||
|
|
@ -436,6 +443,7 @@ class ChatComment(BaseModel, TimestampMixin):
|
||||||
|
|
||||||
# Relationships
|
# Relationships
|
||||||
message = relationship("NewChatMessage", back_populates="comments")
|
message = relationship("NewChatMessage", back_populates="comments")
|
||||||
|
thread = relationship("NewChatThread")
|
||||||
author = relationship("User")
|
author = relationship("User")
|
||||||
parent = relationship(
|
parent = relationship(
|
||||||
"ChatComment", remote_side="ChatComment.id", backref="replies"
|
"ChatComment", remote_side="ChatComment.id", backref="replies"
|
||||||
|
|
|
||||||
|
|
@ -281,8 +281,10 @@ async def create_comment(
|
||||||
detail="You don't have permission to create comments in this search space",
|
detail="You don't have permission to create comments in this search space",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
thread = message.thread
|
||||||
comment = ChatComment(
|
comment = ChatComment(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
|
thread_id=thread.id, # Denormalized for efficient Electric subscriptions
|
||||||
author_id=user.id,
|
author_id=user.id,
|
||||||
content=content,
|
content=content,
|
||||||
)
|
)
|
||||||
|
|
@ -299,7 +301,6 @@ async def create_comment(
|
||||||
user_names = await get_user_names_for_mentions(session, set(mentions_map.keys()))
|
user_names = await get_user_names_for_mentions(session, set(mentions_map.keys()))
|
||||||
|
|
||||||
# Create notifications for mentioned users (excluding author)
|
# Create notifications for mentioned users (excluding author)
|
||||||
thread = message.thread
|
|
||||||
author_name = user.display_name or user.email
|
author_name = user.display_name or user.email
|
||||||
content_preview = render_mentions(content, user_names)
|
content_preview = render_mentions(content, user_names)
|
||||||
for mentioned_user_id, mention_id in mentions_map.items():
|
for mentioned_user_id, mention_id in mentions_map.items():
|
||||||
|
|
@ -391,8 +392,10 @@ async def create_reply(
|
||||||
detail="You don't have permission to create comments in this search space",
|
detail="You don't have permission to create comments in this search space",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
thread = parent_comment.message.thread
|
||||||
reply = ChatComment(
|
reply = ChatComment(
|
||||||
message_id=parent_comment.message_id,
|
message_id=parent_comment.message_id,
|
||||||
|
thread_id=thread.id, # Denormalized for efficient Electric subscriptions
|
||||||
parent_id=comment_id,
|
parent_id=comment_id,
|
||||||
author_id=user.id,
|
author_id=user.id,
|
||||||
content=content,
|
content=content,
|
||||||
|
|
@ -410,7 +413,6 @@ async def create_reply(
|
||||||
user_names = await get_user_names_for_mentions(session, set(mentions_map.keys()))
|
user_names = await get_user_names_for_mentions(session, set(mentions_map.keys()))
|
||||||
|
|
||||||
# Create notifications for mentioned users (excluding author)
|
# Create notifications for mentioned users (excluding author)
|
||||||
thread = parent_comment.message.thread
|
|
||||||
author_name = user.display_name or user.email
|
author_name = user.display_name or user.email
|
||||||
content_preview = render_mentions(content, user_names)
|
content_preview = render_mentions(content, user_names)
|
||||||
for mentioned_user_id, mention_id in mentions_map.items():
|
for mentioned_user_id, mention_id in mentions_map.items():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue