11import CronTime from 'cron-time-generator'
22
3- import { IS_DEV_ENV } from '@crowd/common'
3+ import { ConcurrencyLimiter , IS_DEV_ENV } from '@crowd/common'
44import { READ_DB_CONFIG , getDbConnection } from '@crowd/data-access-layer/src/database'
5- import { fetchNangoIntegrationData } from '@crowd/data-access-layer/src/integrations'
5+ import { fetchNangoIntegrationDataForCheck } from '@crowd/data-access-layer/src/integrations'
66import { pgpQx } from '@crowd/data-access-layer/src/queryExecutor'
77import {
88 ALL_NANGO_INTEGRATIONS ,
@@ -28,10 +28,15 @@ const job: IJobDefinition = {
2828
2929 const dbConnection = await getDbConnection ( READ_DB_CONFIG ( ) , 3 , 0 )
3030
31- const integrationsToTrigger = await fetchNangoIntegrationData ( pgpQx ( dbConnection ) , [
31+ const integrationsToTrigger = await fetchNangoIntegrationDataForCheck ( pgpQx ( dbConnection ) , [
3232 ...new Set ( ALL_NANGO_INTEGRATIONS . map ( nangoIntegrationToPlatform ) ) ,
3333 ] )
3434
35+ const limiter = new ConcurrencyLimiter ( 5 )
36+
37+ // Collect all workflow start operations
38+ const workflowStarts : Array < ( ) => Promise < void > > = [ ]
39+
3540 for ( let i = 0 ; i < integrationsToTrigger . length ; i ++ ) {
3641 const int = integrationsToTrigger [ i ]
3742
@@ -71,10 +76,51 @@ const job: IJobDefinition = {
7176 modifiedAfter : new Date ( ) . toISOString ( ) ,
7277 }
7378
79+ workflowStarts . push ( async ( ) => {
80+ try {
81+ await temporal . workflow . start ( 'processNangoWebhook' , {
82+ taskQueue : 'nango' ,
83+ workflowId : `nango-webhook/${ platform } /${ id } /${ connectionId } /${ model } /cron-triggered` ,
84+ workflowIdReusePolicy :
85+ WorkflowIdReusePolicy . WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE ,
86+ retry : {
87+ maximumAttempts : 10 ,
88+ } ,
89+ args : [ payload ] ,
90+ } )
91+ } catch ( error ) {
92+ if ( error . name === 'WorkflowExecutionAlreadyStartedError' ) {
93+ ctx . log . debug (
94+ {
95+ integrationId : id ,
96+ platform,
97+ model,
98+ connectionId,
99+ } ,
100+ 'Workflow already running, skipping...' ,
101+ )
102+ return
103+ }
104+ throw error
105+ }
106+ } )
107+ }
108+ } else {
109+ const payload : INangoWebhookPayload = {
110+ connectionId : id ,
111+ providerConfigKey : platform ,
112+ syncName : 'not important' ,
113+ model,
114+ responseResults : { added : 1 , updated : 1 , deleted : 1 } ,
115+ syncType : 'INCREMENTAL' ,
116+ modifiedAfter : new Date ( ) . toISOString ( ) ,
117+ }
118+
119+ workflowStarts . push ( async ( ) => {
74120 try {
75121 await temporal . workflow . start ( 'processNangoWebhook' , {
76122 taskQueue : 'nango' ,
77- workflowId : `nango-webhook/${ platform } /${ id } /${ connectionId } / ${ model } /cron-triggered` ,
123+ workflowId : `nango-webhook/${ platform } /${ id } /${ model } /cron-triggered` ,
78124 workflowIdReusePolicy :
79125 WorkflowIdReusePolicy . WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE ,
80126 retry : {
@@ -89,53 +135,40 @@ const job: IJobDefinition = {
89135 integrationId : id ,
90136 platform,
91137 model,
92- connectionId,
93138 } ,
94139 'Workflow already running, skipping...' ,
95140 )
96- continue
141+ return
97142 }
98143 throw error
99144 }
100- }
101- } else {
102- const payload : INangoWebhookPayload = {
103- connectionId : id ,
104- providerConfigKey : platform ,
105- syncName : 'not important' ,
106- model,
107- responseResults : { added : 1 , updated : 1 , deleted : 1 } ,
108- syncType : 'INCREMENTAL' ,
109- modifiedAfter : new Date ( ) . toISOString ( ) ,
110- }
111-
112- try {
113- await temporal . workflow . start ( 'processNangoWebhook' , {
114- taskQueue : 'nango' ,
115- workflowId : `nango-webhook/${ platform } /${ id } /${ model } /cron-triggered` ,
116- workflowIdReusePolicy : WorkflowIdReusePolicy . WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE ,
117- retry : {
118- maximumAttempts : 10 ,
119- } ,
120- args : [ payload ] ,
121- } )
122- } catch ( error ) {
123- if ( error . name === 'WorkflowExecutionAlreadyStartedError' ) {
124- ctx . log . debug (
125- {
126- integrationId : id ,
127- platform,
128- model,
129- } ,
130- 'Workflow already running, skipping...' ,
131- )
132- continue
133- }
134- throw error
135- }
145+ } )
136146 }
137147 }
138148 }
149+
150+ ctx . log . info ( `Triggering nango integration checks with ${ workflowStarts . length } workflows!` )
151+
152+ // Track completed workflows
153+ let completedWorkflows = 0
154+
155+ // Register callback to track completed workflows
156+ limiter . setOnJobComplete ( ( ) => {
157+ completedWorkflows ++
158+ if ( completedWorkflows % 100 === 0 ) {
159+ ctx . log . info ( `Triggered ${ completedWorkflows } nango integrations checks so far...` )
160+ }
161+ } )
162+
163+ // Process all workflow starts with concurrency limit
164+ for ( const workflowStart of workflowStarts ) {
165+ await limiter . schedule ( workflowStart )
166+ }
167+
168+ // Wait for all remaining jobs to complete
169+ await limiter . waitForFinish ( )
170+
171+ ctx . log . info ( `Triggered ${ completedWorkflows } nango integrations checks in total` )
139172 } ,
140173}
141174
0 commit comments