@@ -11,14 +11,16 @@ import {
1111 type BillingAttributionSnapshot ,
1212} from '@/lib/billing/core/billing-attribution'
1313import { resolveTriggerRegion } from '@/lib/core/async-jobs/region'
14- import { executeSync } from '@/lib/knowledge/connectors/sync-engine'
14+ import { executeSync , isConnectorRunnableStatus } from '@/lib/knowledge/connectors/sync-engine'
1515import { isTriggerAvailable } from '@/lib/knowledge/documents/service'
1616
1717const logger = createLogger ( 'ConnectorSyncQueue' )
1818
1919export interface ConnectorSyncPayload {
2020 connectorId : string
2121 fullSync ?: boolean
22+ /** Skip automatic work if the connector is paused or disabled before execution starts. */
23+ requireRunnable ?: boolean
2224 /**
2325 * Force re-hydration + re-indexing of already-synced documents for connectors
2426 * whose rendered content can drift without a hash change (see
@@ -34,6 +36,7 @@ export interface ConnectorSyncPayload {
3436export interface DispatchSyncOptions {
3537 billingAttribution : BillingAttributionSnapshot
3638 fullSync ?: boolean
39+ requireRunnable ?: boolean
3740 rehydrate ?: boolean
3841 requestId ?: string
3942}
@@ -55,6 +58,9 @@ export function assertConnectorSyncPayload(value: unknown): ConnectorSyncPayload
5558 if ( value . fullSync !== undefined && typeof value . fullSync !== 'boolean' ) {
5659 throw new Error ( 'Connector sync payload fullSync must be a boolean when provided' )
5760 }
61+ if ( value . requireRunnable !== undefined && typeof value . requireRunnable !== 'boolean' ) {
62+ throw new Error ( 'Connector sync payload requireRunnable must be a boolean when provided' )
63+ }
5864 if ( value . rehydrate !== undefined && typeof value . rehydrate !== 'boolean' ) {
5965 throw new Error ( 'Connector sync payload rehydrate must be a boolean when provided' )
6066 }
@@ -65,6 +71,7 @@ export function assertConnectorSyncPayload(value: unknown): ConnectorSyncPayload
6571 return {
6672 connectorId : value . connectorId ,
6773 fullSync : value . fullSync as boolean | undefined ,
74+ requireRunnable : value . requireRunnable as boolean | undefined ,
6875 rehydrate : value . rehydrate as boolean | undefined ,
6976 requestId : value . requestId ,
7077 billingAttribution : assertBillingAttributionSnapshot ( value . billingAttribution ) ,
@@ -87,6 +94,7 @@ export async function dispatchSync(
8794 const payload = assertConnectorSyncPayload ( {
8895 connectorId,
8996 fullSync : options ?. fullSync ,
97+ requireRunnable : options ?. requireRunnable ,
9098 rehydrate : options ?. rehydrate ,
9199 requestId,
92100 billingAttribution : options ?. billingAttribution ,
@@ -95,6 +103,7 @@ export async function dispatchSync(
95103 const connectorRows = await db
96104 . select ( {
97105 knowledgeBaseId : knowledgeConnector . knowledgeBaseId ,
106+ connectorStatus : knowledgeConnector . status ,
98107 connectorArchivedAt : knowledgeConnector . archivedAt ,
99108 connectorDeletedAt : knowledgeConnector . deletedAt ,
100109 workspaceId : knowledgeBase . workspaceId ,
@@ -134,6 +143,14 @@ export async function dispatchSync(
134143 } )
135144 return
136145 }
146+ if ( payload . requireRunnable && ! isConnectorRunnableStatus ( row . connectorStatus ) ) {
147+ logger . info ( 'Skipping automatic sync dispatch: connector is not runnable' , {
148+ connectorId,
149+ status : row . connectorStatus ,
150+ requestId,
151+ } )
152+ return
153+ }
137154 if ( ! row . workspaceId ) {
138155 throw new Error ( `Connector ${ connectorId } is missing workspace billing context` )
139156 }
@@ -161,6 +178,7 @@ export async function dispatchSync(
161178
162179 executeSync ( connectorId , {
163180 fullSync : payload . fullSync ,
181+ requireRunnable : payload . requireRunnable ,
164182 rehydrate : payload . rehydrate ,
165183 billingAttribution : payload . billingAttribution ,
166184 } ) . catch ( ( error ) => {
0 commit comments