Skip to content

Commit 0180d43

Browse files
committed
add syncing status
1 parent 2844b76 commit 0180d43

19 files changed

+610
-18645
lines changed

backend/onyx/db/models.py

-1
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,6 @@ class DocumentRetrievalFeedback(Base):
15011501
feedback: Mapped[SearchFeedbackType | None] = mapped_column(
15021502
Enum(SearchFeedbackType, native_enum=False), nullable=True
15031503
)
1504-
15051504
chat_message: Mapped[ChatMessage] = relationship(
15061505
"ChatMessage",
15071506
back_populates="document_feedbacks",

backend/onyx/db/sync_record.py

+31
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,37 @@
1313
logger = setup_logger()
1414

1515

16+
def fetch_paginated_sync_records(
17+
db_session: Session,
18+
entity_id: int,
19+
sync_type: SyncType,
20+
page_num: int,
21+
page_size: int,
22+
) -> tuple[list[SyncRecord], int]:
23+
total_count = (
24+
db_session.query(SyncRecord)
25+
.filter(
26+
SyncRecord.entity_id == entity_id,
27+
SyncRecord.sync_type == sync_type,
28+
)
29+
.count()
30+
)
31+
32+
sync_records = (
33+
db_session.query(SyncRecord)
34+
.filter(
35+
SyncRecord.entity_id == entity_id,
36+
SyncRecord.sync_type == sync_type,
37+
)
38+
.order_by(SyncRecord.sync_start_time.desc())
39+
.offset(page_num * page_size)
40+
.limit(page_size)
41+
.all()
42+
)
43+
44+
return sync_records, total_count
45+
46+
1647
def insert_sync_record(
1748
db_session: Session,
1849
entity_id: int,

backend/onyx/server/documents/cc_pair.py

+83
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from sqlalchemy.exc import IntegrityError
1010
from sqlalchemy.orm import Session
1111

12+
from ee.onyx.db.user_group import fetch_user_group
1213
from onyx.auth.users import current_curator_or_admin_user
1314
from onyx.auth.users import current_user
1415
from onyx.background.celery.celery_utils import get_deletion_attempt_snapshot
@@ -41,6 +42,7 @@
4142
from onyx.db.engine import get_session
4243
from onyx.db.enums import AccessType
4344
from onyx.db.enums import ConnectorCredentialPairStatus
45+
from onyx.db.enums import SyncType
4446
from onyx.db.index_attempt import count_index_attempt_errors_for_cc_pair
4547
from onyx.db.index_attempt import count_index_attempts_for_connector
4648
from onyx.db.index_attempt import get_index_attempt_errors_for_cc_pair
@@ -50,6 +52,7 @@
5052
from onyx.db.models import User
5153
from onyx.db.search_settings import get_active_search_settings_list
5254
from onyx.db.search_settings import get_current_search_settings
55+
from onyx.db.sync_record import fetch_paginated_sync_records
5356
from onyx.redis.redis_connector import RedisConnector
5457
from onyx.redis.redis_pool import get_redis_client
5558
from onyx.server.documents.models import CCPairFullInfo
@@ -60,6 +63,7 @@
6063
from onyx.server.documents.models import DocumentSyncStatus
6164
from onyx.server.documents.models import IndexAttemptSnapshot
6265
from onyx.server.documents.models import PaginatedReturn
66+
from onyx.server.documents.models import SyncRecordSnapshot
6367
from onyx.server.models import StatusResponse
6468
from onyx.utils.logger import setup_logger
6569
from onyx.utils.variable_functionality import fetch_ee_implementation_or_noop
@@ -69,6 +73,85 @@
6973
router = APIRouter(prefix="/manage")
7074

7175

76+
@router.get("/admin/user-group/{group_id}/sync-status")
77+
def get_user_group_sync_status(
78+
group_id: int,
79+
page_num: int = Query(0, ge=0),
80+
page_size: int = Query(10, ge=1, le=1000),
81+
user: User | None = Depends(current_curator_or_admin_user),
82+
db_session: Session = Depends(get_session),
83+
) -> PaginatedReturn[SyncRecordSnapshot]:
84+
user_group = fetch_user_group(db_session, group_id)
85+
if not user_group:
86+
raise HTTPException(status_code=404, detail="User group not found")
87+
88+
sync_records, total_count = fetch_paginated_sync_records(
89+
db_session, group_id, SyncType.USER_GROUP, page_num, page_size
90+
)
91+
92+
return PaginatedReturn(
93+
items=[
94+
SyncRecordSnapshot.from_sync_record_db_model(sync_record)
95+
for sync_record in sync_records
96+
],
97+
total_items=total_count,
98+
)
99+
100+
101+
@router.post("/admin/user-group/{group_id}/sync")
102+
def sync_user_group(
103+
group_id: int,
104+
user: User | None = Depends(current_curator_or_admin_user),
105+
db_session: Session = Depends(get_session),
106+
) -> StatusResponse[None]:
107+
"""Triggers sync of a user group immediately"""
108+
get_current_tenant_id()
109+
110+
user_group = fetch_user_group(db_session, group_id)
111+
if not user_group:
112+
raise HTTPException(status_code=404, detail="User group not found")
113+
114+
# Add logic to actually trigger the sync - this would depend on your implementation
115+
# For example:
116+
# try_creating_usergroup_sync_task(primary_app, group_id, get_redis_client(), tenant_id)
117+
118+
logger.info(f"User group sync queued: group_id={group_id}")
119+
120+
return StatusResponse(
121+
success=True,
122+
message="Successfully created the user group sync task.",
123+
)
124+
125+
126+
@router.get("/admin/cc-pair/{cc_pair_id}/sync-status")
127+
def get_cc_pair_sync_status(
128+
cc_pair_id: int,
129+
page_num: int = Query(0, ge=0),
130+
page_size: int = Query(10, ge=1, le=1000),
131+
user: User | None = Depends(current_curator_or_admin_user),
132+
db_session: Session = Depends(get_session),
133+
) -> PaginatedReturn[SyncRecordSnapshot]:
134+
cc_pair = get_connector_credential_pair_from_id_for_user(
135+
cc_pair_id, db_session, user, get_editable=False
136+
)
137+
if not cc_pair:
138+
raise HTTPException(
139+
status_code=400, detail="CC Pair not found for current user permissions"
140+
)
141+
142+
sync_records, total_count = fetch_paginated_sync_records(
143+
db_session, cc_pair_id, SyncType.EXTERNAL_PERMISSIONS, page_num, page_size
144+
)
145+
146+
return PaginatedReturn(
147+
items=[
148+
SyncRecordSnapshot.from_sync_record_db_model(sync_record)
149+
for sync_record in sync_records
150+
],
151+
total_items=total_count,
152+
)
153+
154+
72155
@router.get("/admin/cc-pair/{cc_pair_id}/index-attempts")
73156
def get_cc_pair_index_attempts(
74157
cc_pair_id: int,

backend/onyx/server/documents/models.py

+24
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
from onyx.connectors.models import InputType
1717
from onyx.db.enums import AccessType
1818
from onyx.db.enums import ConnectorCredentialPairStatus
19+
from onyx.db.enums import SyncStatus
20+
from onyx.db.enums import SyncType
1921
from onyx.db.models import Connector
2022
from onyx.db.models import ConnectorCredentialPair
2123
from onyx.db.models import Credential
2224
from onyx.db.models import Document as DbDocument
2325
from onyx.db.models import IndexAttempt
2426
from onyx.db.models import IndexingStatus
27+
from onyx.db.models import SyncRecord
2528
from onyx.db.models import TaskStatus
2629
from onyx.server.models import FullUserSnapshot
2730
from onyx.server.models import InvitedUserSnapshot
@@ -69,6 +72,26 @@ class ConnectorBase(BaseModel):
6972
indexing_start: datetime | None = None
7073

7174

75+
class SyncRecordSnapshot(BaseModel):
76+
id: int
77+
entity_id: int
78+
sync_type: SyncType
79+
created_at: datetime
80+
num_docs_synced: int
81+
sync_status: SyncStatus
82+
83+
@classmethod
84+
def from_sync_record_db_model(cls, sync_record: SyncRecord) -> "SyncRecordSnapshot":
85+
return cls(
86+
id=sync_record.id,
87+
entity_id=sync_record.entity_id,
88+
sync_type=sync_record.sync_type,
89+
created_at=sync_record.sync_start_time,
90+
num_docs_synced=sync_record.num_docs_synced,
91+
sync_status=sync_record.sync_status,
92+
)
93+
94+
7295
class ConnectorUpdateRequest(ConnectorBase):
7396
access_type: AccessType
7497
groups: list[int] = Field(default_factory=list)
@@ -199,6 +222,7 @@ def from_index_attempt_db_model(
199222
InvitedUserSnapshot,
200223
ChatSessionMinimal,
201224
IndexAttemptErrorPydantic,
225+
SyncRecordSnapshot,
202226
)
203227

204228

0 commit comments

Comments
 (0)