mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
fix: fixed notifications table and Electric SQL replication setup. Removed redirects for upload button
This commit is contained in:
parent
5bd6bd3d67
commit
fede7413fb
6 changed files with 54 additions and 67 deletions
|
|
@ -1,10 +1,11 @@
|
|||
"""Add notifications table
|
||||
"""Add notifications table and Electric SQL replication
|
||||
|
||||
Revision ID: 62
|
||||
Revises: 61
|
||||
|
||||
Note: Electric SQL replication setup (REPLICA IDENTITY FULL and publication)
|
||||
is handled in app/db.py setup_electric_replication() which runs on app startup.
|
||||
Creates notifications table and sets up Electric SQL replication
|
||||
(REPLICA IDENTITY FULL and publication) for notifications,
|
||||
search_source_connectors, and documents tables.
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
|
@ -19,7 +20,7 @@ depends_on: str | Sequence[str] | None = None
|
|||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema - add notifications table."""
|
||||
"""Upgrade schema - add notifications table and Electric SQL replication."""
|
||||
# Create notifications table
|
||||
op.execute(
|
||||
"""
|
||||
|
|
@ -44,6 +45,51 @@ def upgrade() -> None:
|
|||
op.create_index("ix_notifications_created_at", "notifications", ["created_at"])
|
||||
op.create_index("ix_notifications_user_read", "notifications", ["user_id", "read"])
|
||||
|
||||
# Set up Electric SQL replication for real-time sync tables
|
||||
# Set REPLICA IDENTITY FULL (required by Electric SQL for replication)
|
||||
# This logs full row data for UPDATE/DELETE operations in the WAL
|
||||
op.execute("ALTER TABLE notifications REPLICA IDENTITY FULL;")
|
||||
op.execute("ALTER TABLE search_source_connectors REPLICA IDENTITY FULL;")
|
||||
op.execute("ALTER TABLE documents REPLICA IDENTITY FULL;")
|
||||
|
||||
# Add tables to Electric SQL publication for replication if publication exists
|
||||
op.execute(
|
||||
"""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_publication WHERE pubname = 'electric_publication_default') THEN
|
||||
-- Add notifications if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'notifications'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE notifications;
|
||||
END IF;
|
||||
|
||||
-- Add search_source_connectors if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'search_source_connectors'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE search_source_connectors;
|
||||
END IF;
|
||||
|
||||
-- Add documents if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'documents'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE documents;
|
||||
END IF;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema - remove notifications table."""
|
||||
|
|
|
|||
|
|
@ -988,60 +988,6 @@ async def create_db_and_tables():
|
|||
await conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
await setup_indexes()
|
||||
await setup_electric_replication()
|
||||
|
||||
|
||||
async def setup_electric_replication():
|
||||
"""Set up Electric SQL replication for real-time sync tables."""
|
||||
async with engine.begin() as conn:
|
||||
# Set REPLICA IDENTITY FULL (required by Electric SQL for replication)
|
||||
# This logs full row data for UPDATE/DELETE operations in the WAL
|
||||
await conn.execute(text("ALTER TABLE notifications REPLICA IDENTITY FULL;"))
|
||||
await conn.execute(
|
||||
text("ALTER TABLE search_source_connectors REPLICA IDENTITY FULL;")
|
||||
)
|
||||
await conn.execute(text("ALTER TABLE documents REPLICA IDENTITY FULL;"))
|
||||
|
||||
# Add tables to Electric SQL publication for replication
|
||||
# Only add if publication exists and table not already in it
|
||||
await conn.execute(
|
||||
text(
|
||||
"""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_publication WHERE pubname = 'electric_publication_default') THEN
|
||||
-- Add notifications if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'notifications'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE notifications;
|
||||
END IF;
|
||||
|
||||
-- Add search_source_connectors if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'search_source_connectors'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE search_source_connectors;
|
||||
END IF;
|
||||
|
||||
-- Add documents if not already added
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'electric_publication_default'
|
||||
AND tablename = 'documents'
|
||||
) THEN
|
||||
ALTER PUBLICATION electric_publication_default ADD TABLE documents;
|
||||
END IF;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ export default function DocumentsTable() {
|
|||
document_type: "SURFSENSE_DOCS",
|
||||
document_metadata: { source: doc.source },
|
||||
content: doc.content,
|
||||
created_at: doc.created_at || doc.updated_at || new Date().toISOString(),
|
||||
created_at: new Date().toISOString(),
|
||||
search_space_id: -1, // Special value for global docs
|
||||
}));
|
||||
}, [surfsenseDocsResponse]);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import { useAtomValue } from "jotai";
|
||||
import { Upload } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
createContext,
|
||||
type FC,
|
||||
|
|
@ -85,13 +84,11 @@ const DocumentUploadPopupContent: FC<{
|
|||
onOpenChange: (open: boolean) => void;
|
||||
}> = ({ isOpen, onOpenChange }) => {
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const router = useRouter();
|
||||
|
||||
if (!searchSpaceId) return null;
|
||||
|
||||
const handleSuccess = () => {
|
||||
onOpenChange(false);
|
||||
router.push(`/dashboard/${searchSpaceId}/documents`);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { Bell, Check, CheckCheck, Loader2, AlertCircle, CheckCircle2 } from "lucide-react";
|
||||
import { Bell, CheckCheck, Loader2, AlertCircle, CheckCircle2 } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
|
@ -44,7 +44,7 @@ export function NotificationPopup({
|
|||
|
||||
switch (status) {
|
||||
case "in_progress":
|
||||
return <Loader2 className="h-4 w-4 text-blue-500 animate-spin" />;
|
||||
return <Loader2 className="h-4 w-4 text-white animate-spin" />;
|
||||
case "completed":
|
||||
return <CheckCircle2 className="h-4 w-4 text-green-500" />;
|
||||
case "failed":
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import { useAtom } from "jotai";
|
||||
import { CheckCircle2, FileType, Info, Loader2, Tag, Upload, X } from "lucide-react";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useCallback, useMemo, useRef, useState } from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
|
|
@ -116,7 +115,6 @@ export function DocumentUploadTab({
|
|||
onAccordionStateChange,
|
||||
}: DocumentUploadTabProps) {
|
||||
const t = useTranslations("upload_documents");
|
||||
const router = useRouter();
|
||||
const [files, setFiles] = useState<File[]>([]);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
const [accordionValue, setAccordionValue] = useState<string>("");
|
||||
|
|
@ -185,7 +183,7 @@ export function DocumentUploadTab({
|
|||
setUploadProgress(100);
|
||||
trackDocumentUploadSuccess(Number(searchSpaceId), files.length);
|
||||
toast(t("upload_initiated"), { description: t("upload_initiated_desc") });
|
||||
onSuccess?.() || router.push(`/dashboard/${searchSpaceId}/documents`);
|
||||
onSuccess?.();
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
clearInterval(progressInterval);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue