Skip to content

Commit 3868baa

Browse files
committed
fix(trigger): let workers see that Trigger.dev is available
Workers run Trigger.dev by definition, but the flag saying so is read from the environment and had only ever been set on the app container. isTriggerAvailable() was therefore false inside every task run, so work a task dispatched silently took the in-process fallback instead of the queue it was written for. Document processing is where this showed: a connector sync chunked and embedded its documents itself, five at a time, rather than handing them to the document-processing queue. The queue's concurrency limit, the per-document task's machine, retry policy and duration budget all sat unused, and a sync with thousands of documents ran until it hit its own max duration. It also explains why that task has no runs for connector-synced knowledge bases at all. Asserting the flag here is safe because the same check still requires TRIGGER_SECRET_KEY, which only the Trigger.dev runtime provides: anywhere dispatching is not actually possible the flag stays ineffective and behaviour is unchanged. Dispatch failure is now recoverable rather than silent. Only a total failure raised before, so one failed batch left its documents at pending with nothing recording why. Those are processed in-process instead, which costs the caller the time it hoped to hand to the queue but does not drop the work. That path was unreachable from a worker until this change made dispatching happen there.
1 parent 9ee1b81 commit 3868baa

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

apps/sim/lib/knowledge/documents/service.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ async function dispatchViaBatchTrigger(
721721
): Promise<number> {
722722
let dispatched = 0
723723
const batchIds: string[] = []
724+
const undispatched: DocumentProcessingPayload[] = []
724725
const region = await resolveTriggerRegion()
725726
for (let i = 0; i < jobPayloads.length; i += TRIGGER_BATCH_SIZE) {
726727
const chunk = jobPayloads.slice(i, i + TRIGGER_BATCH_SIZE)
@@ -747,11 +748,27 @@ async function dispatchViaBatchTrigger(
747748
logger.error(`[${requestId}] Failed to batchTrigger ${chunk.length} document jobs`, {
748749
error: getErrorMessage(error),
749750
})
751+
undispatched.push(...chunk)
750752
}
751753
}
752754
if (batchIds.length > 0) {
753755
logger.info(`[${requestId}] Trigger.dev batches dispatched`, { batchIds })
754756
}
757+
758+
/**
759+
* Only a total dispatch failure raises, so a chunk that failed on its own used
760+
* to leave its documents sitting at `pending` with nothing recording why —
761+
* invisible until the stuck-document sweep happened to pick them up, and never
762+
* if they aged out of its window first. Running them here costs the caller time
763+
* it hoped to hand to the queue, which is the point: the work still happens.
764+
*/
765+
if (undispatched.length > 0) {
766+
logger.warn(
767+
`[${requestId}] Processing ${undispatched.length} documents in-process after failed enqueue`
768+
)
769+
dispatched += await dispatchInProcess(undispatched, requestId)
770+
}
771+
755772
return dispatched
756773
}
757774

apps/sim/trigger.config.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,23 @@ export default defineConfig({
7373
'@daytona/sdk',
7474
],
7575
extensions: [
76-
syncEnvVars(() => [{ name: 'DB_APP_NAME', value: 'sim-trigger' }]),
76+
syncEnvVars(() => [
77+
{ name: 'DB_APP_NAME', value: 'sim-trigger' },
78+
/**
79+
* Workers run Trigger.dev by definition, but the flag that says so is
80+
* read from the environment and was only ever set on the app container.
81+
* `isTriggerAvailable()` therefore returned false inside every worker, so
82+
* anything a task dispatched — document processing above all — silently
83+
* took the in-process path instead of the queue it was written for. A
84+
* connector sync ended up chunking and embedding thousands of documents
85+
* itself, five at a time, and running until it hit its max duration.
86+
*
87+
* Safe to assert here because the check also requires TRIGGER_SECRET_KEY,
88+
* which only the Trigger.dev runtime provides: where dispatching is not
89+
* actually possible this stays false and nothing changes.
90+
*/
91+
{ name: 'TRIGGER_DEV_ENABLED', value: 'TRUE' },
92+
]),
7793
additionalFiles({
7894
files: [
7995
'./lib/execution/isolated-vm-worker.cjs',

0 commit comments

Comments
 (0)