(
entries: { webhook: WebhookRecord; workflow: WorkflowRecord }[],
processFn: (entry: {
webhook: WebhookRecord
workflow: WorkflowRecord
}) => Promise<'success' | 'failure'>,
logger: Logger
)
| 106 | * Returns aggregate success/failure counts. |
| 107 | */ |
| 108 | export async function runWithConcurrency( |
| 109 | entries: { webhook: WebhookRecord; workflow: WorkflowRecord }[], |
| 110 | processFn: (entry: { |
| 111 | webhook: WebhookRecord |
| 112 | workflow: WorkflowRecord |
| 113 | }) => Promise<'success' | 'failure'>, |
| 114 | logger: Logger |
| 115 | ): Promise<{ successCount: number; failureCount: number }> { |
| 116 | const running: Promise<void>[] = [] |
| 117 | let successCount = 0 |
| 118 | let failureCount = 0 |
| 119 | |
| 120 | for (const entry of entries) { |
| 121 | const promise: Promise<void> = processFn(entry) |
| 122 | .then((result) => { |
| 123 | if (result === 'success') { |
| 124 | successCount++ |
| 125 | } else { |
| 126 | failureCount++ |
| 127 | } |
| 128 | }) |
| 129 | .catch((err) => { |
| 130 | logger.error('Unexpected error in webhook processing:', err) |
| 131 | failureCount++ |
| 132 | }) |
| 133 | .finally(() => { |
| 134 | const idx = running.indexOf(promise) |
| 135 | if (idx !== -1) running.splice(idx, 1) |
| 136 | }) |
| 137 | |
| 138 | running.push(promise) |
| 139 | |
| 140 | if (running.length >= CONCURRENCY) { |
| 141 | await Promise.race(running) |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | await Promise.allSettled(running) |
| 146 | |
| 147 | return { successCount, failureCount } |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Atomically merge provider-specific config fields into `webhook.provider_config`. |
no test coverage detected