feat(kb): harden sync engine and add connector audit logging#3697
feat(kb): harden sync engine and add connector audit logging#3697waleedlatif1 merged 5 commits intostagingfrom
Conversation
- Fix stuck syncing status: added finally block in executeSync + stale lock recovery in cron scheduler (2hr TTL) - Fix token expiry mid-sync: refresh OAuth token between pagination pages and before deferred content hydration - GitHub deferred content loading: use Git blob SHA for change detection, only fetch content for new/changed docs - Add network error keywords to isRetryableError (fetch failed, econnreset, etc.) - Extract sanitizeStorageTitle helper to fix S3 key length limit issues - Add audit logging for connector CRUD, sync triggers, document exclude/restore, and resource restoration paths
PR SummaryMedium Risk Overview Reduces GitHub connector API load. Adds audit coverage for KB operations. New Also hardens storage key generation by sanitizing/truncating document titles, expands retryable network error detection, and includes small Tailwind class-order fixes in loading skeletons. Written by Cursor Bugbot for commit e0649ad. Configure here. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile SummaryThis PR significantly hardens the knowledge base sync engine with crash recovery, mid-sync token refresh, deferred GitHub content loading, network retry improvements, S3 key length fixes, and comprehensive audit logging across connector CRUD, document operations, and resource restore paths. Key changes:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Cron as Cron Job
participant SyncRoute as /connectors/sync
participant Engine as executeSync
participant GitHub as GitHub API
participant DB as Database
participant S3 as S3 Storage
Cron->>SyncRoute: GET (scheduled)
SyncRoute->>DB: Reset stale syncing connectors (>2hr TTL)
SyncRoute->>Engine: dispatchSync(connectorId)
Engine->>DB: Acquire sync lock (set status=syncing)
Note over Engine: syncExitedCleanly = false
loop For each page
alt OAuth connector
Engine->>Engine: resolveAccessToken() — refresh token
end
Engine->>GitHub: listDocuments() — returns lightweight stubs (contentDeferred=true)
GitHub-->>Engine: ExternalDocument stubs (contentHash = git-sha:{sha})
end
Engine->>DB: Fetch existing docs + excluded list
Engine->>Engine: Diff stubs vs existing (hash compare)
loop For each batch of pending ops
alt Has deferred ops
Engine->>Engine: resolveAccessToken() — refresh token
Engine->>GitHub: getDocument() per deferred stub
GitHub-->>Engine: Full content + blob SHA hash
end
Engine->>S3: uploadFile (sanitizeStorageTitle ≤200 chars)
Engine->>DB: upsert document records
end
Engine->>DB: Set status=active, update lastSyncAt
Note over Engine: syncExitedCleanly = true
Engine-->>SyncRoute: SyncResult
Note over Engine: finally block — no-op if syncExitedCleanly
|
…ion, resourceName - Replace DB-read finally block with local syncExitedCleanly flag to avoid race condition - Propagate fullDoc.contentHash during deferred content hydration - Add resourceName to file restore audit record
|
@greptile |
|
@cursor review |
Summary
finallyblock inexecuteSyncto reset stalesyncingstatus on crash, plus cron-based stale lock detection (2hr TTL) that recovers connectors stuck insyncingand schedules retry in 10minlistDocumentsnow returns lightweight stubs using Git blob SHA as contentHash (no blob fetches). Content is only fetched viagetDocumentfor new/changed documents, eliminating thousands of unnecessary API calls for large reposfetch failed,econnreset,econnrefused,etimedout,enetunreach,socket hang up,network errortoisRetryableErrorsanitizeStorageTitlehelper that truncates titles to 200 chars, fixing "Your key is too long" errorsrecordAuditcalls for connector CRUD, manual sync triggers, document exclude/restore operations, and restoration paths (KB, tables, workflows, files)Type of Change
Testing
Tested manually
Checklist