@agent-native/core 0.122.2 → 0.122.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +12 -0
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +182 -0
- package/corpus/core/src/integrations/a2a-continuations-store.ts +122 -12
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +127 -0
- package/corpus/core/src/integrations/integration-campaigns-store.ts +1039 -0
- package/corpus/core/src/integrations/integration-durable-dispatch.ts +28 -3
- package/corpus/core/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/corpus/core/src/integrations/plugin.ts +453 -35
- package/corpus/core/src/integrations/webhook-handler.ts +469 -11
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +7 -3
- package/corpus/templates/content/app/components/editor/body-hydration.ts +10 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -0
- package/corpus/templates/content/app/root.tsx +12 -1
- package/corpus/templates/content/changelog/2026-07-23-new-pages-open-immediately-while-slow-network-work-continues.md +6 -0
- package/corpus/templates/content/changelog/2026-07-25-database-preview-actions-open-reliably.md +6 -0
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +7 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +7 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/a2a-continuation-processor.d.ts +14 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +134 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -0
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +99 -13
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts +16 -0
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -0
- package/dist/integrations/integration-campaign-recovery.js +94 -0
- package/dist/integrations/integration-campaign-recovery.js.map +1 -0
- package/dist/integrations/integration-campaigns-store.d.ts +121 -0
- package/dist/integrations/integration-campaigns-store.d.ts.map +1 -0
- package/dist/integrations/integration-campaigns-store.js +784 -0
- package/dist/integrations/integration-campaigns-store.js.map +1 -0
- package/dist/integrations/integration-durable-dispatch.d.ts +3 -0
- package/dist/integrations/integration-durable-dispatch.d.ts.map +1 -1
- package/dist/integrations/integration-durable-dispatch.js +22 -3
- package/dist/integrations/integration-durable-dispatch.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +325 -18
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +16 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +368 -13
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
- package/src/agent/run-loop-with-resume.ts +12 -0
- package/src/integrations/a2a-continuation-processor.ts +182 -0
- package/src/integrations/a2a-continuations-store.ts +122 -12
- package/src/integrations/integration-campaign-recovery.ts +127 -0
- package/src/integrations/integration-campaigns-store.ts +1039 -0
- package/src/integrations/integration-durable-dispatch.ts +28 -3
- package/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/src/integrations/plugin.ts +453 -35
- package/src/integrations/webhook-handler.ts +469 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-campaigns-store.js","sourceRoot":"","sources":["../../src/integrations/integration-campaigns-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n intType,\n isPostgres,\n type DbExec,\n type DbExecStatement,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\n\nlet initPromise: Promise<void> | undefined;\n\nconst MAX_PROGRESS_REF_CHARS = 1_024;\nconst MAX_CHECKPOINT_CHARS = 8_192;\nconst MAX_ERROR_MESSAGE_CHARS = 2_000;\nconst MAX_DUE_LIST_LIMIT = 100;\nconst A2A_WAITING_CHECKPOINT = '{\"waitingForA2A\":true}';\n\nexport type IntegrationCampaignStatus =\n | \"pending\"\n | \"processing\"\n | \"waiting\"\n | \"completed\"\n | \"failed\";\n\nexport interface IntegrationCampaign {\n id: string;\n integrationTaskId: string;\n threadId: string;\n turnId: string;\n status: IntegrationCampaignStatus;\n chunkCount: number;\n currentRunId: string | null;\n leaseToken: string | null;\n leaseExpiresAt: number | null;\n nextRunAt: number;\n progressRef: string | null;\n checkpoint: string | null;\n errorMessage: string | null;\n createdAt: number;\n updatedAt: number;\n completedAt: number | null;\n}\n\nexport type ClaimIntegrationCampaignResult =\n | { kind: \"claimed\"; campaign: IntegrationCampaign }\n | { kind: \"not-due\" }\n | { kind: \"chunk-limit\"; campaign: IntegrationCampaign };\n\nfunction buildCreateSql(): string {\n return `CREATE TABLE IF NOT EXISTS integration_campaigns (\n id TEXT PRIMARY KEY,\n integration_task_id TEXT NOT NULL UNIQUE,\n thread_id TEXT NOT NULL,\n turn_id TEXT NOT NULL,\n status TEXT NOT NULL,\n chunk_count ${intType()} NOT NULL DEFAULT 0,\n current_run_id TEXT,\n lease_token TEXT,\n lease_expires_at ${intType()},\n next_run_at ${intType()} NOT NULL,\n progress_ref TEXT,\n checkpoint TEXT,\n error_message TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n completed_at ${intType()}\n )`;\n}\n\nasync function ensureTable(): Promise<void> {\n if (!initPromise) {\n initPromise = (async () => {\n const createSql = buildCreateSql();\n if (isPostgres()) {\n await ensureTableExists(\"integration_campaigns\", createSql);\n await ensureIndexExists(\n \"idx_integration_campaigns_due\",\n \"CREATE INDEX IF NOT EXISTS idx_integration_campaigns_due ON integration_campaigns(status, next_run_at)\",\n );\n await ensureIndexExists(\n \"idx_integration_campaigns_lease\",\n \"CREATE INDEX IF NOT EXISTS idx_integration_campaigns_lease ON integration_campaigns(status, lease_expires_at)\",\n );\n return;\n }\n\n const client = getDbExec();\n await client.execute(createSql);\n await client.execute(\n \"CREATE INDEX IF NOT EXISTS idx_integration_campaigns_due ON integration_campaigns(status, next_run_at)\",\n );\n await client.execute(\n \"CREATE INDEX IF NOT EXISTS idx_integration_campaigns_lease ON integration_campaigns(status, lease_expires_at)\",\n );\n })().catch((error) => {\n initPromise = undefined;\n throw error;\n });\n }\n return initPromise;\n}\n\nexport async function ensureIntegrationCampaignsTable(): Promise<void> {\n await ensureTable();\n}\n\nfunction boundedOpaqueValue(\n value: string | null | undefined,\n maxLength: number,\n name: string,\n): string | null {\n if (value == null) return null;\n if (value.length > maxLength) {\n throw new Error(`${name} exceeds ${maxLength} characters`);\n }\n return value;\n}\n\nfunction rowToCampaign(row: Record<string, unknown>): IntegrationCampaign {\n return {\n id: String(row.id),\n integrationTaskId: String(row.integration_task_id),\n threadId: String(row.thread_id),\n turnId: String(row.turn_id),\n status: row.status as IntegrationCampaignStatus,\n chunkCount: Number(row.chunk_count ?? 0),\n currentRunId: (row.current_run_id as string | null) ?? null,\n leaseToken: (row.lease_token as string | null) ?? null,\n leaseExpiresAt:\n row.lease_expires_at == null ? null : Number(row.lease_expires_at),\n nextRunAt: Number(row.next_run_at ?? 0),\n progressRef: (row.progress_ref as string | null) ?? null,\n checkpoint: (row.checkpoint as string | null) ?? null,\n errorMessage: (row.error_message as string | null) ?? null,\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n completedAt: row.completed_at == null ? null : Number(row.completed_at),\n };\n}\n\nfunction isDuplicateCampaignError(error: unknown): boolean {\n const candidate = error as { code?: string; message?: string } | null;\n if (!candidate) return false;\n if (candidate.code === \"23505\") return true;\n const message = String(candidate.message ?? \"\").toLowerCase();\n return (\n message.includes(\"unique\") ||\n message.includes(\"duplicate entry\") ||\n message.includes(\"duplicate key\")\n );\n}\n\nexport async function getIntegrationCampaign(\n id: string,\n): Promise<IntegrationCampaign | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: \"SELECT * FROM integration_campaigns WHERE id = ? LIMIT 1\",\n args: [id],\n });\n return rows[0] ? rowToCampaign(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getIntegrationCampaignForTask(\n integrationTaskId: string,\n): Promise<IntegrationCampaign | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: \"SELECT * FROM integration_campaigns WHERE integration_task_id = ? LIMIT 1\",\n args: [integrationTaskId],\n });\n return rows[0] ? rowToCampaign(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function createIntegrationCampaign(input: {\n integrationTaskId: string;\n threadId: string;\n turnId: string;\n progressRef?: string | null;\n checkpoint?: string | null;\n nextRunAt?: number;\n}): Promise<IntegrationCampaign> {\n await ensureTable();\n const now = Date.now();\n const id = `integration-campaign-${now}-${Math.random().toString(36).slice(2, 10)}`;\n const progressRef = boundedOpaqueValue(\n input.progressRef,\n MAX_PROGRESS_REF_CHARS,\n \"progressRef\",\n );\n const checkpoint = boundedOpaqueValue(\n input.checkpoint,\n MAX_CHECKPOINT_CHARS,\n \"checkpoint\",\n );\n\n try {\n await getDbExec().execute({\n sql: `INSERT INTO integration_campaigns\n (id, integration_task_id, thread_id, turn_id, status, chunk_count,\n next_run_at, progress_ref, checkpoint, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.integrationTaskId,\n input.threadId,\n input.turnId,\n \"pending\",\n 0,\n input.nextRunAt ?? now,\n progressRef,\n checkpoint,\n now,\n now,\n ],\n });\n } catch (error) {\n if (!isDuplicateCampaignError(error)) throw error;\n const existing = await getIntegrationCampaignForTask(\n input.integrationTaskId,\n );\n if (existing) return existing;\n throw error;\n }\n\n const campaign = await getIntegrationCampaign(id);\n if (!campaign) throw new Error(\"Created integration campaign was not found\");\n return campaign;\n}\n\nfunction affectedRows(result: unknown): number {\n const value = result as { rowsAffected?: number; rowCount?: number };\n return Number(value.rowsAffected ?? value.rowCount ?? 0);\n}\n\nexport async function claimIntegrationCampaign(\n id: string,\n input: {\n runId: string;\n leaseToken: string;\n leaseDurationMs: number;\n maxChunks: number;\n },\n): Promise<ClaimIntegrationCampaignResult> {\n await ensureTable();\n if (!Number.isFinite(input.leaseDurationMs) || input.leaseDurationMs <= 0) {\n throw new Error(\"leaseDurationMs must be positive\");\n }\n if (!Number.isInteger(input.maxChunks) || input.maxChunks <= 0) {\n throw new Error(\"maxChunks must be a positive integer\");\n }\n\n const now = Date.now();\n const leaseExpiresAt = now + input.leaseDurationMs;\n const dueClause = `(status IN ('pending', 'waiting') AND next_run_at <= ?)\n OR (status = 'processing' AND lease_expires_at IS NOT NULL AND lease_expires_at <= ?)`;\n const result = await getDbExec().execute({\n sql: isPostgres()\n ? `UPDATE integration_campaigns\n SET status = ?, chunk_count = CASE WHEN status = 'waiting' OR checkpoint = ? THEN chunk_count ELSE chunk_count + 1 END, current_run_id = ?,\n lease_token = ?, lease_expires_at = ?, updated_at = ?, error_message = NULL\n WHERE id = ? AND (status = 'waiting' OR checkpoint = ? OR chunk_count < ?) AND (${dueClause})\n RETURNING *`\n : `UPDATE integration_campaigns\n SET status = ?, chunk_count = CASE WHEN status = 'waiting' OR checkpoint = ? THEN chunk_count ELSE chunk_count + 1 END, current_run_id = ?,\n lease_token = ?, lease_expires_at = ?, updated_at = ?, error_message = NULL\n WHERE id = ? AND (status = 'waiting' OR checkpoint = ? OR chunk_count < ?) AND (${dueClause})`,\n args: [\n \"processing\",\n A2A_WAITING_CHECKPOINT,\n input.runId,\n input.leaseToken,\n leaseExpiresAt,\n now,\n id,\n A2A_WAITING_CHECKPOINT,\n input.maxChunks,\n now,\n now,\n ],\n });\n if (isPostgres()) {\n const row = result.rows?.[0];\n if (row)\n return {\n kind: \"claimed\",\n campaign: rowToCampaign(row as Record<string, unknown>),\n };\n } else if (affectedRows(result) > 0) {\n const campaign = await getIntegrationCampaign(id);\n if (\n campaign &&\n campaign.status === \"processing\" &&\n campaign.currentRunId === input.runId &&\n campaign.leaseToken === input.leaseToken\n ) {\n return { kind: \"claimed\", campaign };\n }\n return { kind: \"not-due\" };\n }\n\n const campaign = await getIntegrationCampaign(id);\n const waitingForA2A = campaign?.checkpoint === A2A_WAITING_CHECKPOINT;\n const exhaustedAndRecoverable =\n campaign &&\n campaign.chunkCount >= input.maxChunks &&\n !waitingForA2A &&\n (campaign.status === \"pending\" ||\n (campaign.status === \"processing\" &&\n (campaign.leaseExpiresAt == null || campaign.leaseExpiresAt <= now)));\n if (exhaustedAndRecoverable) {\n return { kind: \"chunk-limit\", campaign };\n }\n return { kind: \"not-due\" };\n}\n\nexport async function claimIntegrationCampaignDeliveryForTask(\n integrationTaskId: string,\n input: { runId: string; leaseToken: string; leaseDurationMs: number },\n): Promise<IntegrationCampaign | null> {\n await ensureTable();\n if (!Number.isFinite(input.leaseDurationMs) || input.leaseDurationMs <= 0) {\n throw new Error(\"leaseDurationMs must be positive\");\n }\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: isPostgres()\n ? `UPDATE integration_campaigns\n SET status = 'processing', current_run_id = ?, lease_token = ?,\n lease_expires_at = ?, updated_at = ?\n WHERE integration_task_id = ?\n AND (status IN ('pending', 'waiting') OR\n (status = 'processing' AND\n (lease_expires_at IS NULL OR lease_expires_at <= ?)))\n RETURNING *`\n : `UPDATE integration_campaigns\n SET status = 'processing', current_run_id = ?, lease_token = ?,\n lease_expires_at = ?, updated_at = ?\n WHERE integration_task_id = ?\n AND (status IN ('pending', 'waiting') OR\n (status = 'processing' AND\n (lease_expires_at IS NULL OR lease_expires_at <= ?)))`,\n args: [\n input.runId,\n input.leaseToken,\n now + input.leaseDurationMs,\n now,\n integrationTaskId,\n now,\n ],\n });\n if (isPostgres()) {\n const row = result.rows?.[0];\n return row ? rowToCampaign(row as Record<string, unknown>) : null;\n }\n if (affectedRows(result) === 0) return null;\n const campaign = await getIntegrationCampaignForTask(integrationTaskId);\n return campaign?.currentRunId === input.runId &&\n campaign.leaseToken === input.leaseToken\n ? campaign\n : null;\n}\n\nfunction leaseWhere(): string {\n return \"id = ? AND status = 'processing' AND current_run_id = ? AND lease_token = ?\";\n}\n\nexport async function heartbeatIntegrationCampaign(\n id: string,\n input: { runId: string; leaseToken: string; leaseDurationMs: number },\n): Promise<boolean> {\n await ensureTable();\n if (!Number.isFinite(input.leaseDurationMs) || input.leaseDurationMs <= 0) {\n throw new Error(\"leaseDurationMs must be positive\");\n }\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET lease_expires_at = ?, updated_at = ?\n WHERE ${leaseWhere()}`,\n args: [now + input.leaseDurationMs, now, id, input.runId, input.leaseToken],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function scheduleNextIntegrationCampaign(\n id: string,\n input: {\n runId: string;\n leaseToken: string;\n nextRunAt: number;\n progressRef?: string | null;\n checkpoint?: string | null;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const progressRef = boundedOpaqueValue(\n input.progressRef,\n MAX_PROGRESS_REF_CHARS,\n \"progressRef\",\n );\n const checkpoint = boundedOpaqueValue(\n input.checkpoint,\n MAX_CHECKPOINT_CHARS,\n \"checkpoint\",\n );\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET status = ?, current_run_id = NULL, lease_token = NULL, lease_expires_at = NULL,\n next_run_at = ?, progress_ref = COALESCE(?, progress_ref),\n checkpoint = COALESCE(?, checkpoint), updated_at = ?\n WHERE ${leaseWhere()}`,\n args: [\n \"pending\",\n input.nextRunAt,\n progressRef,\n checkpoint,\n now,\n id,\n input.runId,\n input.leaseToken,\n ],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function waitForA2AIntegrationCampaign(\n id: string,\n input: {\n runId: string;\n leaseToken: string;\n nextRunAt: number;\n progressRef?: string | null;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const progressRef = boundedOpaqueValue(\n input.progressRef,\n MAX_PROGRESS_REF_CHARS,\n \"progressRef\",\n );\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET status = 'waiting', current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, next_run_at = ?,\n progress_ref = COALESCE(?, progress_ref),\n checkpoint = ?, updated_at = ?\n WHERE ${leaseWhere()}`,\n args: [\n input.nextRunAt,\n progressRef,\n A2A_WAITING_CHECKPOINT,\n now,\n id,\n input.runId,\n input.leaseToken,\n ],\n });\n return affectedRows(result) > 0;\n}\n\nasync function finishIntegrationCampaign(\n id: string,\n input: {\n runId: string;\n leaseToken: string;\n status: \"completed\" | \"failed\";\n errorMessage?: string;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const errorMessage = boundedOpaqueValue(\n input.errorMessage,\n MAX_ERROR_MESSAGE_CHARS,\n \"errorMessage\",\n );\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET status = ?, current_run_id = NULL, lease_token = NULL, lease_expires_at = NULL,\n progress_ref = NULL, checkpoint = NULL, error_message = ?,\n updated_at = ?, completed_at = ?\n WHERE ${leaseWhere()}`,\n args: [\n input.status,\n errorMessage,\n now,\n now,\n id,\n input.runId,\n input.leaseToken,\n ],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function completeIntegrationCampaign(\n id: string,\n input: { runId: string; leaseToken: string },\n): Promise<boolean> {\n return finishIntegrationCampaign(id, { ...input, status: \"completed\" });\n}\n\nexport async function completeIntegrationCampaignTask(\n id: string,\n input: {\n integrationTaskId: string;\n runId: string;\n leaseToken: string;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const previousWriteGuard = isPostgres() ? \"\" : \"AND changes() = 1\";\n const statements: DbExecStatement[] = [\n {\n sql: `UPDATE integration_campaigns\n SET status = 'completed', current_run_id = NULL,\n lease_token = NULL, lease_expires_at = NULL,\n progress_ref = NULL, checkpoint = NULL, error_message = NULL,\n updated_at = ?, completed_at = ?\n WHERE id = ? AND integration_task_id = ?\n AND status = 'processing'\n AND current_run_id = ? AND lease_token = ?`,\n args: [\n now,\n now,\n id,\n input.integrationTaskId,\n input.runId,\n input.leaseToken,\n ],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET status = 'completed', payload = '{}', error_message = NULL,\n updated_at = ?, completed_at = ?\n WHERE id = ? AND status = 'processing'\n ${previousWriteGuard}\n AND EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE id = ? AND integration_task_id = ?\n AND status = 'completed' AND updated_at = ?\n AND completed_at = ?\n )`,\n args: [\n now,\n now,\n input.integrationTaskId,\n id,\n input.integrationTaskId,\n now,\n now,\n ],\n },\n ];\n const db = getDbExec();\n if (db.atomicBatch) {\n const results = await db.atomicBatch(statements);\n return (\n results.length === statements.length &&\n results.every((result) => affectedRows(result) > 0)\n );\n }\n if (db.transaction) {\n return await db.transaction(async (tx) => {\n const campaignResult = await tx.execute(statements[0]!);\n if (affectedRows(campaignResult) === 0) return false;\n const taskResult = await tx.execute(statements[1]!);\n if (affectedRows(taskResult) === 0) {\n throw new Error(\"Campaign completion transition lost its task custody\");\n }\n return true;\n });\n }\n throw new Error(\"Database does not support atomic campaign completion\");\n}\n\nexport async function failIntegrationCampaign(\n id: string,\n input: { runId: string; leaseToken: string; errorMessage: string },\n): Promise<boolean> {\n return finishIntegrationCampaign(id, { ...input, status: \"failed\" });\n}\n\nexport async function failExhaustedIntegrationCampaign(\n id: string,\n input: { maxChunks: number; errorMessage: string },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const errorMessage = boundedOpaqueValue(\n input.errorMessage,\n MAX_ERROR_MESSAGE_CHARS,\n \"errorMessage\",\n );\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET status = 'failed', current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, progress_ref = NULL, checkpoint = NULL,\n error_message = ?, updated_at = ?, completed_at = ?\n WHERE id = ? AND chunk_count >= ?\n AND (checkpoint IS NULL OR checkpoint <> ?)\n AND (status = 'pending' OR\n (status = 'processing' AND\n (lease_expires_at IS NULL OR lease_expires_at <= ?)))`,\n args: [\n errorMessage,\n now,\n now,\n id,\n input.maxChunks,\n A2A_WAITING_CHECKPOINT,\n now,\n ],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function terminalizeIntegrationCampaignForTask(\n integrationTaskId: string,\n input: { status: \"completed\" | \"failed\"; errorMessage?: string },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const errorMessage = boundedOpaqueValue(\n input.errorMessage,\n MAX_ERROR_MESSAGE_CHARS,\n \"errorMessage\",\n );\n const result = await getDbExec().execute({\n sql: `UPDATE integration_campaigns\n SET status = ?, current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, progress_ref = NULL, checkpoint = NULL,\n error_message = ?, updated_at = ?, completed_at = ?\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'waiting')`,\n args: [input.status, errorMessage, now, now, integrationTaskId],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function failIntegrationCampaignTaskDeliveryContainment(\n integrationTaskId: string,\n errorMessage: string,\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const boundedError =\n boundedOpaqueValue(errorMessage, MAX_ERROR_MESSAGE_CHARS, \"errorMessage\") ??\n \"Delivery transition failed\";\n const statements: DbExecStatement[] = [\n {\n sql: `UPDATE integration_campaigns\n SET status = 'failed', current_run_id = NULL,\n lease_token = NULL, lease_expires_at = NULL,\n progress_ref = NULL, checkpoint = NULL, error_message = ?,\n updated_at = ?, completed_at = ?\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'waiting')`,\n args: [boundedError, now, now, integrationTaskId],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET status = 'failed', payload = '{}', error_message = ?,\n updated_at = ?, completed_at = ?\n WHERE id = ? AND status = 'processing'\n AND NOT EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'waiting')\n )`,\n args: [boundedError, now, now, integrationTaskId, integrationTaskId],\n },\n ];\n const db = getDbExec();\n if (db.atomicBatch) {\n const results = await db.atomicBatch(statements);\n return (\n results.length === statements.length && affectedRows(results[1]!) > 0\n );\n }\n if (db.transaction) {\n return await db.transaction(async (tx) => {\n await tx.execute(statements[0]!);\n const taskResult = await tx.execute(statements[1]!);\n return affectedRows(taskResult) > 0;\n });\n }\n throw new Error(\"Database does not support atomic delivery containment\");\n}\n\nfunction disabledCampaignAndTaskStatements(\n integrationTaskId: string,\n errorMessage: string,\n): DbExecStatement[] {\n const now = Date.now();\n return [\n {\n sql: `UPDATE integration_campaigns\n SET status = 'failed', current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, progress_ref = NULL, checkpoint = NULL,\n error_message = ?, updated_at = ?, completed_at = ?\n WHERE integration_task_id = ?\n AND status IN ('pending', 'processing', 'waiting')`,\n args: [errorMessage, now, now, integrationTaskId],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET status = 'failed', payload = '{}', external_event_key = NULL,\n error_message = ?, updated_at = ?, completed_at = ?\n WHERE id = ? AND status = 'processing'`,\n args: [errorMessage, now, now, integrationTaskId],\n },\n ];\n}\n\nasync function executeStatementsWithDb(\n db: DbExec,\n statements: readonly DbExecStatement[],\n): Promise<void> {\n for (const statement of statements) await db.execute(statement);\n}\n\n/**\n * Fail closed when a durable campaign's rollout scope is removed. Both rows\n * transition in one transaction so the per-thread processing lock cannot be\n * stranded while the campaign is no longer recoverable.\n */\nexport async function failDisabledIntegrationCampaignTask(\n integrationTaskId: string,\n errorMessage = \"Durable integration campaign was disabled for this scope\",\n): Promise<void> {\n await ensureTable();\n const boundedError =\n boundedOpaqueValue(errorMessage, MAX_ERROR_MESSAGE_CHARS, \"errorMessage\") ??\n \"Durable integration campaign was disabled\";\n const db = getDbExec();\n const statements = disabledCampaignAndTaskStatements(\n integrationTaskId,\n boundedError,\n );\n if (db.atomicBatch) {\n await db.atomicBatch(statements);\n return;\n }\n if (db.transaction) {\n await db.transaction((tx) => executeStatementsWithDb(tx, statements));\n return;\n }\n throw new Error(\"Database does not support atomic campaign cancellation\");\n}\n\nexport async function transitionIntegrationCampaignTaskToDeliveryRetry(\n integrationTaskId: string,\n input: {\n payload: string;\n errorMessage: string;\n campaignStatus: \"completed\" | \"failed\";\n campaignId: string;\n runId: string;\n leaseToken: string;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const errorMessage =\n boundedOpaqueValue(\n input.errorMessage,\n MAX_ERROR_MESSAGE_CHARS,\n \"errorMessage\",\n ) ?? \"Integration response delivery needs retry\";\n const previousWriteGuard = isPostgres() ? \"\" : \"AND changes() = 1\";\n const statements: DbExecStatement[] = [\n {\n sql: `UPDATE integration_campaigns\n SET status = ?, current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, progress_ref = NULL, checkpoint = NULL,\n error_message = ?, updated_at = ?, completed_at = ?\n WHERE id = ? AND integration_task_id = ?\n AND status = 'processing'\n AND current_run_id = ? AND lease_token = ?`,\n args: [\n input.campaignStatus,\n input.campaignStatus === \"failed\" ? errorMessage : null,\n now,\n now,\n input.campaignId,\n integrationTaskId,\n input.runId,\n input.leaseToken,\n ],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET status = 'pending', payload = ?, error_message = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'\n ${previousWriteGuard}\n AND EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE id = ? AND integration_task_id = ?\n AND status = ? AND updated_at = ? AND completed_at = ?\n AND current_run_id IS NULL AND lease_token IS NULL\n )`,\n args: [\n input.payload,\n errorMessage,\n now,\n integrationTaskId,\n input.campaignId,\n integrationTaskId,\n input.campaignStatus,\n now,\n now,\n ],\n },\n ];\n const db = getDbExec();\n if (db.atomicBatch) {\n const results = await db.atomicBatch(statements);\n return (\n results.length === statements.length &&\n results.every((result) => affectedRows(result) > 0)\n );\n }\n if (db.transaction) {\n return await db.transaction(async (tx) => {\n const campaignResult = await tx.execute(statements[0]!);\n if (affectedRows(campaignResult) === 0) return false;\n const taskResult = await tx.execute(statements[1]!);\n if (affectedRows(taskResult) === 0) {\n throw new Error(\n \"Campaign delivery retry lease transition lost its race\",\n );\n }\n return true;\n });\n }\n throw new Error(\"Database does not support atomic campaign delivery retry\");\n}\n\nexport async function transitionIntegrationCampaignTaskToA2AReceiptRetry(\n integrationTaskId: string,\n input: {\n payload: string;\n errorMessage: string;\n campaignId: string;\n runId: string;\n leaseToken: string;\n nextRunAt: number;\n },\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const errorMessage =\n boundedOpaqueValue(\n input.errorMessage,\n MAX_ERROR_MESSAGE_CHARS,\n \"errorMessage\",\n ) ?? \"A2A partial response history needs retry\";\n const previousWriteGuard = isPostgres() ? \"\" : \"AND changes() = 1\";\n const statements: DbExecStatement[] = [\n {\n sql: `UPDATE integration_campaigns\n SET status = 'waiting', current_run_id = NULL, lease_token = NULL,\n lease_expires_at = NULL, next_run_at = ?, checkpoint = ?,\n error_message = NULL, updated_at = ?\n WHERE id = ? AND integration_task_id = ?\n AND status = 'processing'\n AND current_run_id = ? AND lease_token = ?`,\n args: [\n input.nextRunAt,\n A2A_WAITING_CHECKPOINT,\n now,\n input.campaignId,\n integrationTaskId,\n input.runId,\n input.leaseToken,\n ],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET payload = ?, error_message = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'\n ${previousWriteGuard}\n AND EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE id = ? AND integration_task_id = ?\n AND status = 'waiting' AND checkpoint = ?\n AND updated_at = ? AND current_run_id IS NULL\n AND lease_token IS NULL\n )`,\n args: [\n input.payload,\n errorMessage,\n now,\n integrationTaskId,\n input.campaignId,\n integrationTaskId,\n A2A_WAITING_CHECKPOINT,\n now,\n ],\n },\n ];\n const db = getDbExec();\n if (db.atomicBatch) {\n const results = await db.atomicBatch(statements);\n return (\n results.length === statements.length &&\n results.every((result) => affectedRows(result) > 0)\n );\n }\n if (db.transaction) {\n return await db.transaction(async (tx) => {\n const campaignResult = await tx.execute(statements[0]!);\n if (affectedRows(campaignResult) === 0) return false;\n const taskResult = await tx.execute(statements[1]!);\n if (affectedRows(taskResult) === 0) {\n throw new Error(\"A2A receipt custody transition lost its race\");\n }\n return true;\n });\n }\n throw new Error(\"Database does not support atomic A2A receipt custody\");\n}\n\nexport async function refreshIntegrationCampaignTaskA2AReceiptRetry(\n integrationTaskId: string,\n input: { payload: string; errorMessage: string },\n): Promise<boolean> {\n await ensureTable();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_pending_tasks\n SET payload = ?, error_message = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'\n AND EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE integration_task_id = ? AND status = 'waiting'\n AND checkpoint = ?\n )`,\n args: [\n input.payload,\n input.errorMessage.slice(0, MAX_ERROR_MESSAGE_CHARS),\n Date.now(),\n integrationTaskId,\n integrationTaskId,\n A2A_WAITING_CHECKPOINT,\n ],\n });\n return affectedRows(result) > 0;\n}\n\nexport async function completeIntegrationCampaignTaskAfterA2A(\n integrationTaskId: string,\n): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const previousWriteGuard = isPostgres() ? \"\" : \"AND changes() = 1\";\n const statements: DbExecStatement[] = [\n {\n sql: `UPDATE integration_campaigns\n SET status = 'completed', current_run_id = NULL,\n lease_token = NULL, lease_expires_at = NULL,\n progress_ref = NULL, checkpoint = NULL, error_message = NULL,\n updated_at = ?, completed_at = ?\n WHERE integration_task_id = ? AND status = 'waiting'\n AND checkpoint = ?`,\n args: [now, now, integrationTaskId, A2A_WAITING_CHECKPOINT],\n },\n {\n sql: `UPDATE integration_pending_tasks\n SET status = 'completed', payload = '{}', error_message = NULL,\n updated_at = ?, completed_at = ?\n WHERE id = ? AND status = 'processing'\n ${previousWriteGuard}\n AND EXISTS (\n SELECT 1 FROM integration_campaigns\n WHERE integration_task_id = ? AND status = 'completed'\n AND updated_at = ? AND completed_at = ?\n )`,\n args: [now, now, integrationTaskId, integrationTaskId, now, now],\n },\n ];\n const db = getDbExec();\n if (db.atomicBatch) {\n const results = await db.atomicBatch(statements);\n return (\n results.length === statements.length &&\n results.every((result) => affectedRows(result) > 0)\n );\n }\n if (db.transaction) {\n return await db.transaction(async (tx) => {\n const campaignResult = await tx.execute(statements[0]!);\n if (affectedRows(campaignResult) === 0) return false;\n const taskResult = await tx.execute(statements[1]!);\n if (affectedRows(taskResult) === 0) {\n throw new Error(\"A2A parent completion transition lost its race\");\n }\n return true;\n });\n }\n throw new Error(\"Database does not support atomic A2A parent completion\");\n}\n\nexport async function listDueIntegrationCampaignIds(\n limit = 25,\n): Promise<string[]> {\n await ensureTable();\n const boundedLimit = Math.max(\n 1,\n Math.min(Math.floor(limit), MAX_DUE_LIST_LIMIT),\n );\n const now = Date.now();\n const { rows } = await getDbExec().execute({\n sql: `SELECT id FROM integration_campaigns\n WHERE (status IN ('pending', 'waiting') AND next_run_at <= ?)\n OR (status = 'processing' AND lease_expires_at IS NOT NULL AND lease_expires_at <= ?)\n ORDER BY next_run_at ASC, id ASC\n LIMIT ?`,\n args: [now, now, boundedLimit],\n });\n return rows.map((row) => String((row as Record<string, unknown>).id));\n}\n\nexport async function hasActiveIntegrationCampaign(\n integrationTaskId: string,\n): Promise<boolean> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT 1 AS active FROM integration_campaigns\n WHERE integration_task_id = ? AND status IN ('pending', 'processing', 'waiting')\n LIMIT 1`,\n args: [integrationTaskId],\n });\n return rows.length > 0;\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { INTEGRATION_DURABLE_DISPATCH_ENV, INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV, INTEGRATION_PROCESS_TASK_PATH, INTEGRATION_RETRY_SWEEP_PATH, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, isIntegrationDurableDispatchConfigured } from "./integration-durable-dispatch-config.js";
|
|
2
2
|
export { INTEGRATION_DURABLE_DISPATCH_ENV, INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV, INTEGRATION_PROCESS_TASK_PATH, INTEGRATION_RETRY_SWEEP_PATH, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, isIntegrationDurableDispatchConfigured, };
|
|
3
3
|
export type IntegrationDispatchOutcome = "background-acknowledged" | "portable-unconfirmed" | "failed";
|
|
4
|
+
export declare const INTEGRATION_CAMPAIGN_PROCESSOR_FIELD = "__integrationCampaignContinuation";
|
|
4
5
|
export interface IntegrationDispatchTaskScope {
|
|
5
6
|
platform: string;
|
|
6
7
|
externalThreadId: string;
|
|
@@ -19,5 +20,7 @@ export declare function dispatchPendingIntegrationTask(input: {
|
|
|
19
20
|
event?: unknown;
|
|
20
21
|
baseUrl?: string;
|
|
21
22
|
portableSettleMs?: number;
|
|
23
|
+
campaignContinuation?: boolean;
|
|
24
|
+
allowPortableConfirmedReceiptReconciliation?: boolean;
|
|
22
25
|
}): Promise<IntegrationDispatchOutcome>;
|
|
23
26
|
//# sourceMappingURL=integration-durable-dispatch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-durable-dispatch.d.ts","sourceRoot":"","sources":["../../src/integrations/integration-durable-dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,6BAA6B,EAC7B,4BAA4B,EAC5B,qCAAqC,EACrC,sCAAsC,EACvC,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,6BAA6B,EAC7B,4BAA4B,EAC5B,qCAAqC,EACrC,sCAAsC,GACvC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAClC,yBAAyB,GACzB,sBAAsB,GACtB,QAAQ,CAAC;AAEb,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,4BAA4B,GACjC,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,0CAA0C,IACtD,+BAA+B,EAAE,GACjC,IAAI,CAeP;AAiBD,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAkBT;AA4BD,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,4BAA4B,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"integration-durable-dispatch.d.ts","sourceRoot":"","sources":["../../src/integrations/integration-durable-dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,6BAA6B,EAC7B,4BAA4B,EAC5B,qCAAqC,EACrC,sCAAsC,EACvC,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,6BAA6B,EAC7B,4BAA4B,EAC5B,qCAAqC,EACrC,sCAAsC,GACvC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAClC,yBAAyB,GACzB,sBAAsB,GACtB,QAAQ,CAAC;AAEb,eAAO,MAAM,oCAAoC,sCACZ,CAAC;AAEtC,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,4BAA4B,GACjC,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,0CAA0C,IACtD,+BAA+B,EAAE,GACjC,IAAI,CAeP;AAiBD,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAkBT;AA4BD,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,4BAA4B,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,2CAA2C,CAAC,EAAE,OAAO,CAAC;CACvD,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAuEtC"}
|
|
@@ -4,6 +4,7 @@ import { fireInternalDispatch } from "../server/self-dispatch.js";
|
|
|
4
4
|
import { INTEGRATION_DURABLE_DISPATCH_ENV, INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV, INTEGRATION_PROCESS_TASK_PATH, INTEGRATION_RETRY_SWEEP_PATH, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, isIntegrationDurableDispatchConfigured, } from "./integration-durable-dispatch-config.js";
|
|
5
5
|
import { recordPendingTaskDispatchAttempt } from "./pending-tasks-store.js";
|
|
6
6
|
export { INTEGRATION_DURABLE_DISPATCH_ENV, INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV, INTEGRATION_PROCESS_TASK_PATH, INTEGRATION_RETRY_SWEEP_PATH, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, isIntegrationDurableDispatchConfigured, };
|
|
7
|
+
export const INTEGRATION_CAMPAIGN_PROCESSOR_FIELD = "__integrationCampaignContinuation";
|
|
7
8
|
export function integrationDispatchScopeValue(task) {
|
|
8
9
|
const value = task.platformContext?.channelId;
|
|
9
10
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -71,6 +72,12 @@ function logDispatch(taskId, outcome, startedAt) {
|
|
|
71
72
|
export async function dispatchPendingIntegrationTask(input) {
|
|
72
73
|
const startedAt = Date.now();
|
|
73
74
|
const durable = isIntegrationDurableDispatchEnabledForTask(input.task);
|
|
75
|
+
if (input.campaignContinuation &&
|
|
76
|
+
!durable &&
|
|
77
|
+
!input.allowPortableConfirmedReceiptReconciliation) {
|
|
78
|
+
logDispatch(input.taskId, "failed", startedAt);
|
|
79
|
+
return "failed";
|
|
80
|
+
}
|
|
74
81
|
if (durable) {
|
|
75
82
|
const backgroundPath = resolveDurableBackgroundDispatchPath(INTEGRATION_PROCESS_TASK_PATH);
|
|
76
83
|
try {
|
|
@@ -81,11 +88,16 @@ export async function dispatchPendingIntegrationTask(input) {
|
|
|
81
88
|
taskId: input.taskId,
|
|
82
89
|
body: {
|
|
83
90
|
[AGENT_BACKGROUND_PROCESSOR_FIELD]: AGENT_BACKGROUND_PROCESSOR_INTEGRATION,
|
|
91
|
+
...(input.campaignContinuation
|
|
92
|
+
? { [INTEGRATION_CAMPAIGN_PROCESSOR_FIELD]: true }
|
|
93
|
+
: {}),
|
|
84
94
|
},
|
|
85
95
|
awaitResponse: true,
|
|
86
96
|
responseTimeoutMs: 2_000,
|
|
87
97
|
});
|
|
88
|
-
|
|
98
|
+
if (!input.campaignContinuation) {
|
|
99
|
+
await recordDispatch(input.taskId, "background-acknowledged");
|
|
100
|
+
}
|
|
89
101
|
logDispatch(input.taskId, "background-acknowledged", startedAt);
|
|
90
102
|
return "background-acknowledged";
|
|
91
103
|
}
|
|
@@ -99,15 +111,22 @@ export async function dispatchPendingIntegrationTask(input) {
|
|
|
99
111
|
baseUrl: input.baseUrl,
|
|
100
112
|
path: INTEGRATION_PROCESS_TASK_PATH,
|
|
101
113
|
taskId: input.taskId,
|
|
114
|
+
body: input.campaignContinuation
|
|
115
|
+
? { [INTEGRATION_CAMPAIGN_PROCESSOR_FIELD]: true }
|
|
116
|
+
: undefined,
|
|
102
117
|
settleMs: input.portableSettleMs,
|
|
103
118
|
});
|
|
104
|
-
|
|
119
|
+
if (!input.campaignContinuation) {
|
|
120
|
+
await recordDispatch(input.taskId, "portable-unconfirmed");
|
|
121
|
+
}
|
|
105
122
|
logDispatch(input.taskId, "portable-unconfirmed", startedAt);
|
|
106
123
|
return "portable-unconfirmed";
|
|
107
124
|
}
|
|
108
125
|
catch (error) {
|
|
109
126
|
console.error(`[integrations] Portable dispatch failed for ${input.taskId}:`, error);
|
|
110
|
-
|
|
127
|
+
if (!input.campaignContinuation) {
|
|
128
|
+
await recordDispatch(input.taskId, "failed");
|
|
129
|
+
}
|
|
111
130
|
logDispatch(input.taskId, "failed", startedAt);
|
|
112
131
|
return "failed";
|
|
113
132
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-durable-dispatch.js","sourceRoot":"","sources":["../../src/integrations/integration-durable-dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { hasConfiguredA2ASecret } from \"../a2a/auth-policy.js\";\nimport {\n AGENT_BACKGROUND_PROCESSOR_FIELD,\n AGENT_BACKGROUND_PROCESSOR_INTEGRATION,\n dispatchPathTargetsNetlifyBackgroundFunction,\n resolveDurableBackgroundDispatchPath,\n} from \"../agent/durable-background.js\";\nimport { fireInternalDispatch } from \"../server/self-dispatch.js\";\nimport {\n INTEGRATION_DURABLE_DISPATCH_ENV,\n INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV,\n INTEGRATION_PROCESS_TASK_PATH,\n INTEGRATION_RETRY_SWEEP_PATH,\n INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT,\n isIntegrationDurableDispatchConfigured,\n} from \"./integration-durable-dispatch-config.js\";\nimport { recordPendingTaskDispatchAttempt } from \"./pending-tasks-store.js\";\n\nexport {\n INTEGRATION_DURABLE_DISPATCH_ENV,\n INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV,\n INTEGRATION_PROCESS_TASK_PATH,\n INTEGRATION_RETRY_SWEEP_PATH,\n INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT,\n isIntegrationDurableDispatchConfigured,\n};\n\nexport type IntegrationDispatchOutcome =\n | \"background-acknowledged\"\n | \"portable-unconfirmed\"\n | \"failed\";\n\nexport interface IntegrationDispatchTaskScope {\n platform: string;\n externalThreadId: string;\n platformContext?: Record<string, unknown>;\n}\n\nexport interface IntegrationDurableDispatchScope {\n platform: string;\n value: string;\n}\n\nexport function integrationDispatchScopeValue(\n task: IntegrationDispatchTaskScope,\n): string | null {\n const value = task.platformContext?.channelId;\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nexport function configuredIntegrationDurableDispatchScopes():\n | IntegrationDurableDispatchScope[]\n | null {\n const raw = process.env.AGENT_INTEGRATION_DURABLE_DISPATCH_SCOPES;\n if (!raw?.trim()) return null;\n return raw\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean)\n .map((scope) => {\n const separator = scope.indexOf(\":\");\n return {\n platform: separator > 0 ? scope.slice(0, separator) : \"\",\n value: separator > 0 ? scope.slice(separator + 1) : \"\",\n };\n })\n .filter((scope) => scope.platform && scope.value);\n}\n\nfunction taskScopeCandidates(task: IntegrationDispatchTaskScope): string[] {\n const candidates = [\n `${task.platform}:*`,\n `${task.platform}:${task.externalThreadId}`,\n ];\n const explicitScope = integrationDispatchScopeValue(task);\n if (explicitScope) {\n candidates.push(`${task.platform}:${explicitScope}`);\n } else if (task.platform === \"slack\") {\n const channelId = task.externalThreadId.split(\":\")[2];\n if (channelId) candidates.push(`slack:${channelId}`);\n }\n return candidates;\n}\n\nexport function isIntegrationDurableDispatchEnabledForTask(\n task: IntegrationDispatchTaskScope,\n): boolean {\n if (!isIntegrationDurableDispatchConfigured()) return false;\n const scopes = configuredIntegrationDurableDispatchScopes();\n if (\n scopes &&\n !taskScopeCandidates(task).some((candidate) =>\n scopes.some((scope) => `${scope.platform}:${scope.value}` === candidate),\n )\n ) {\n return false;\n }\n const path = resolveDurableBackgroundDispatchPath(\n INTEGRATION_PROCESS_TASK_PATH,\n );\n return (\n dispatchPathTargetsNetlifyBackgroundFunction(path) &&\n hasConfiguredA2ASecret()\n );\n}\n\nasync function recordDispatch(\n taskId: string,\n outcome: IntegrationDispatchOutcome,\n): Promise<void> {\n try {\n await recordPendingTaskDispatchAttempt(taskId, outcome);\n } catch (error) {\n console.error(\n `[integrations] Failed to record dispatch outcome for ${taskId}:`,\n error,\n );\n }\n}\n\nfunction logDispatch(\n taskId: string,\n outcome: IntegrationDispatchOutcome,\n startedAt: number,\n): void {\n console.info(\"[integrations] pending task dispatch\", {\n taskId,\n outcome,\n durationMs: Date.now() - startedAt,\n });\n}\n\nexport async function dispatchPendingIntegrationTask(input: {\n taskId: string;\n task: IntegrationDispatchTaskScope;\n event?: unknown;\n baseUrl?: string;\n portableSettleMs?: number;\n}): Promise<IntegrationDispatchOutcome> {\n const startedAt = Date.now();\n const durable = isIntegrationDurableDispatchEnabledForTask(input.task);\n if (durable) {\n const backgroundPath = resolveDurableBackgroundDispatchPath(\n INTEGRATION_PROCESS_TASK_PATH,\n );\n try {\n await fireInternalDispatch({\n event: input.event,\n baseUrl: input.baseUrl,\n path: backgroundPath,\n taskId: input.taskId,\n body: {\n [AGENT_BACKGROUND_PROCESSOR_FIELD]:\n AGENT_BACKGROUND_PROCESSOR_INTEGRATION,\n },\n awaitResponse: true,\n responseTimeoutMs: 2_000,\n });\n await recordDispatch(input.taskId, \"background-acknowledged\");\n logDispatch(input.taskId, \"background-acknowledged\", startedAt);\n return \"background-acknowledged\";\n } catch (error) {\n console.error(\n `[integrations] Background dispatch failed for ${input.taskId}; trying the portable processor:`,\n error,\n );\n }\n }\n\n try {\n await fireInternalDispatch({\n event: input.event,\n baseUrl: input.baseUrl,\n path: INTEGRATION_PROCESS_TASK_PATH,\n taskId: input.taskId,\n settleMs: input.portableSettleMs,\n });\n await recordDispatch(input.taskId, \"portable-unconfirmed\");\n logDispatch(input.taskId, \"portable-unconfirmed\", startedAt);\n return \"portable-unconfirmed\";\n } catch (error) {\n console.error(\n `[integrations] Portable dispatch failed for ${input.taskId}:`,\n error,\n );\n await recordDispatch(input.taskId, \"failed\");\n logDispatch(input.taskId, \"failed\", startedAt);\n return \"failed\";\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"integration-durable-dispatch.js","sourceRoot":"","sources":["../../src/integrations/integration-durable-dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { hasConfiguredA2ASecret } from \"../a2a/auth-policy.js\";\nimport {\n AGENT_BACKGROUND_PROCESSOR_FIELD,\n AGENT_BACKGROUND_PROCESSOR_INTEGRATION,\n dispatchPathTargetsNetlifyBackgroundFunction,\n resolveDurableBackgroundDispatchPath,\n} from \"../agent/durable-background.js\";\nimport { fireInternalDispatch } from \"../server/self-dispatch.js\";\nimport {\n INTEGRATION_DURABLE_DISPATCH_ENV,\n INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV,\n INTEGRATION_PROCESS_TASK_PATH,\n INTEGRATION_RETRY_SWEEP_PATH,\n INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT,\n isIntegrationDurableDispatchConfigured,\n} from \"./integration-durable-dispatch-config.js\";\nimport { recordPendingTaskDispatchAttempt } from \"./pending-tasks-store.js\";\n\nexport {\n INTEGRATION_DURABLE_DISPATCH_ENV,\n INTEGRATION_DURABLE_DISPATCH_SCOPES_ENV,\n INTEGRATION_PROCESS_TASK_PATH,\n INTEGRATION_RETRY_SWEEP_PATH,\n INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT,\n isIntegrationDurableDispatchConfigured,\n};\n\nexport type IntegrationDispatchOutcome =\n | \"background-acknowledged\"\n | \"portable-unconfirmed\"\n | \"failed\";\n\nexport const INTEGRATION_CAMPAIGN_PROCESSOR_FIELD =\n \"__integrationCampaignContinuation\";\n\nexport interface IntegrationDispatchTaskScope {\n platform: string;\n externalThreadId: string;\n platformContext?: Record<string, unknown>;\n}\n\nexport interface IntegrationDurableDispatchScope {\n platform: string;\n value: string;\n}\n\nexport function integrationDispatchScopeValue(\n task: IntegrationDispatchTaskScope,\n): string | null {\n const value = task.platformContext?.channelId;\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nexport function configuredIntegrationDurableDispatchScopes():\n | IntegrationDurableDispatchScope[]\n | null {\n const raw = process.env.AGENT_INTEGRATION_DURABLE_DISPATCH_SCOPES;\n if (!raw?.trim()) return null;\n return raw\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean)\n .map((scope) => {\n const separator = scope.indexOf(\":\");\n return {\n platform: separator > 0 ? scope.slice(0, separator) : \"\",\n value: separator > 0 ? scope.slice(separator + 1) : \"\",\n };\n })\n .filter((scope) => scope.platform && scope.value);\n}\n\nfunction taskScopeCandidates(task: IntegrationDispatchTaskScope): string[] {\n const candidates = [\n `${task.platform}:*`,\n `${task.platform}:${task.externalThreadId}`,\n ];\n const explicitScope = integrationDispatchScopeValue(task);\n if (explicitScope) {\n candidates.push(`${task.platform}:${explicitScope}`);\n } else if (task.platform === \"slack\") {\n const channelId = task.externalThreadId.split(\":\")[2];\n if (channelId) candidates.push(`slack:${channelId}`);\n }\n return candidates;\n}\n\nexport function isIntegrationDurableDispatchEnabledForTask(\n task: IntegrationDispatchTaskScope,\n): boolean {\n if (!isIntegrationDurableDispatchConfigured()) return false;\n const scopes = configuredIntegrationDurableDispatchScopes();\n if (\n scopes &&\n !taskScopeCandidates(task).some((candidate) =>\n scopes.some((scope) => `${scope.platform}:${scope.value}` === candidate),\n )\n ) {\n return false;\n }\n const path = resolveDurableBackgroundDispatchPath(\n INTEGRATION_PROCESS_TASK_PATH,\n );\n return (\n dispatchPathTargetsNetlifyBackgroundFunction(path) &&\n hasConfiguredA2ASecret()\n );\n}\n\nasync function recordDispatch(\n taskId: string,\n outcome: IntegrationDispatchOutcome,\n): Promise<void> {\n try {\n await recordPendingTaskDispatchAttempt(taskId, outcome);\n } catch (error) {\n console.error(\n `[integrations] Failed to record dispatch outcome for ${taskId}:`,\n error,\n );\n }\n}\n\nfunction logDispatch(\n taskId: string,\n outcome: IntegrationDispatchOutcome,\n startedAt: number,\n): void {\n console.info(\"[integrations] pending task dispatch\", {\n taskId,\n outcome,\n durationMs: Date.now() - startedAt,\n });\n}\n\nexport async function dispatchPendingIntegrationTask(input: {\n taskId: string;\n task: IntegrationDispatchTaskScope;\n event?: unknown;\n baseUrl?: string;\n portableSettleMs?: number;\n campaignContinuation?: boolean;\n allowPortableConfirmedReceiptReconciliation?: boolean;\n}): Promise<IntegrationDispatchOutcome> {\n const startedAt = Date.now();\n const durable = isIntegrationDurableDispatchEnabledForTask(input.task);\n if (\n input.campaignContinuation &&\n !durable &&\n !input.allowPortableConfirmedReceiptReconciliation\n ) {\n logDispatch(input.taskId, \"failed\", startedAt);\n return \"failed\";\n }\n if (durable) {\n const backgroundPath = resolveDurableBackgroundDispatchPath(\n INTEGRATION_PROCESS_TASK_PATH,\n );\n try {\n await fireInternalDispatch({\n event: input.event,\n baseUrl: input.baseUrl,\n path: backgroundPath,\n taskId: input.taskId,\n body: {\n [AGENT_BACKGROUND_PROCESSOR_FIELD]:\n AGENT_BACKGROUND_PROCESSOR_INTEGRATION,\n ...(input.campaignContinuation\n ? { [INTEGRATION_CAMPAIGN_PROCESSOR_FIELD]: true }\n : {}),\n },\n awaitResponse: true,\n responseTimeoutMs: 2_000,\n });\n if (!input.campaignContinuation) {\n await recordDispatch(input.taskId, \"background-acknowledged\");\n }\n logDispatch(input.taskId, \"background-acknowledged\", startedAt);\n return \"background-acknowledged\";\n } catch (error) {\n console.error(\n `[integrations] Background dispatch failed for ${input.taskId}; trying the portable processor:`,\n error,\n );\n }\n }\n\n try {\n await fireInternalDispatch({\n event: input.event,\n baseUrl: input.baseUrl,\n path: INTEGRATION_PROCESS_TASK_PATH,\n taskId: input.taskId,\n body: input.campaignContinuation\n ? { [INTEGRATION_CAMPAIGN_PROCESSOR_FIELD]: true }\n : undefined,\n settleMs: input.portableSettleMs,\n });\n if (!input.campaignContinuation) {\n await recordDispatch(input.taskId, \"portable-unconfirmed\");\n }\n logDispatch(input.taskId, \"portable-unconfirmed\", startedAt);\n return \"portable-unconfirmed\";\n } catch (error) {\n console.error(\n `[integrations] Portable dispatch failed for ${input.taskId}:`,\n error,\n );\n if (!input.campaignContinuation) {\n await recordDispatch(input.taskId, \"failed\");\n }\n logDispatch(input.taskId, \"failed\", startedAt);\n return \"failed\";\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-tasks-retry-job.d.ts","sourceRoot":"","sources":["../../src/integrations/pending-tasks-retry-job.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pending-tasks-retry-job.d.ts","sourceRoot":"","sources":["../../src/integrations/pending-tasks-retry-job.ts"],"names":[],"mappings":"AAsEA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAkDD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,CAAC,EAAE,MAAM,GAAG,wBAAwB,GACxC,OAAO,CAAC,uBAAuB,CAAC,CAoLlC;AAcD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,IAAI,CA0BP;AAED,2BAA2B;AAC3B,wBAAgB,wBAAwB,IAAI,IAAI,CAU/C"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDbExec } from "../db/client.js";
|
|
2
|
+
import { hasActiveIntegrationCampaign } from "./integration-campaigns-store.js";
|
|
2
3
|
import { configuredIntegrationDurableDispatchScopes, dispatchPendingIntegrationTask, isIntegrationDurableDispatchEnabledForTask, } from "./integration-durable-dispatch.js";
|
|
3
4
|
import { ensurePendingTasksTable, MAX_PENDING_TASK_ATTEMPTS, } from "./pending-tasks-store.js";
|
|
4
5
|
/**
|
|
@@ -173,6 +174,11 @@ export async function retryStuckPendingTasks(input) {
|
|
|
173
174
|
return result;
|
|
174
175
|
for (const row of stuckRows) {
|
|
175
176
|
try {
|
|
177
|
+
if (row.status === "processing" &&
|
|
178
|
+
(await hasActiveIntegrationCampaign(row.id))) {
|
|
179
|
+
result.skipped += 1;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
176
182
|
// Cap retries — mark failed and move on so the row stops bouncing
|
|
177
183
|
// between pending and processing forever.
|
|
178
184
|
if (row.attempts >= MAX_PENDING_TASK_ATTEMPTS) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-tasks-retry-job.js","sourceRoot":"","sources":["../../src/integrations/pending-tasks-retry-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec } from \"../db/client.js\";\nimport {\n configuredIntegrationDurableDispatchScopes,\n dispatchPendingIntegrationTask,\n isIntegrationDurableDispatchEnabledForTask,\n} from \"./integration-durable-dispatch.js\";\nimport {\n ensurePendingTasksTable,\n MAX_PENDING_TASK_ATTEMPTS,\n} from \"./pending-tasks-store.js\";\n\n/**\n * Retries stuck integration webhook tasks.\n *\n * The integration webhook flow enqueues work into `integration_pending_tasks`\n * (see `pending-tasks-store.ts`) and then fires a self-webhook to the\n * `/_agent-native/integrations/process-task` endpoint to drain the queue.\n * If that initial dispatch is lost (e.g. transient network blip), the\n * row stays in `pending` forever. Likewise, if the processor is killed mid-\n * processing (function timeout, container shutdown), a row can remain in\n * `processing` forever.\n *\n * The in-process fallback runs every 60s. Durable deployments also invoke the\n * same bounded sweep from an external scheduler so recovery does not depend on\n * a serverless process remaining alive.\n *\n * Each sweep re-fires the processor endpoint for tasks that\n * look stuck:\n * - status='pending' AND created_at older than 90s (initial dispatch lost)\n * - status='processing' AND updated_at older than the host-specific\n * function budget (75s on serverless, 5min elsewhere)\n *\n * Retries are capped at MAX_ATTEMPTS attempts; after that the row is marked\n * `failed` permanently so it stops being retried.\n *\n * If the `integration_pending_tasks` table does not yet exist (e.g. older\n * deploy that hasn't run the new webhook flow), this job no-ops silently\n * rather than spamming logs.\n */\n\nconst RETRY_INTERVAL_MS = 60_000;\n/** Tasks pending longer than this are considered stuck on initial dispatch */\nconst PENDING_STUCK_AFTER_MS = 90_000;\n/** Tasks \"processing\" longer than this are considered killed mid-flight. */\nconst DEFAULT_PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\nconst SERVERLESS_PROCESSING_STUCK_AFTER_MS = 75_000;\nconst DURABLE_BACKGROUND_PROCESSING_STUCK_AFTER_MS = 16 * 60 * 1000;\n/** After this many attempts we give up and mark the task failed */\nconst DEFAULT_SWEEP_LIMIT = 100;\n\nlet retryInterval: ReturnType<typeof setInterval> | null = null;\nlet initialTimer: ReturnType<typeof setTimeout> | null = null;\nlet activeWebhookBaseUrl: string | undefined;\n/**\n * Whether the table exists. Cached after first probe so we don't log every\n * minute when the queue isn't in use yet on a given deployment.\n */\nlet tableExists: boolean | null = null;\n\ninterface StuckTaskRow {\n id: string;\n platform: string;\n externalThreadId: string;\n status: string;\n attempts: number;\n updatedAt: number;\n dispatchScope: string | null;\n}\n\nexport interface PendingTasksSweepResult {\n selected: number;\n dispatched: number;\n markedFailed: number;\n skipped: number;\n dispatchFailed: number;\n}\n\nexport interface PendingTasksSweepOptions {\n webhookBaseUrl?: string;\n limit?: number;\n durableOnly?: boolean;\n}\n\nfunction affectedRows(result: unknown): number {\n return Number(\n (result as { rowsAffected?: number }).rowsAffected ??\n (result as { rowCount?: number }).rowCount ??\n 0,\n );\n}\n\nfunction isMissingPendingTasksTableError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return /no such table|relation .* does not exist|undefined_table/i.test(\n message,\n );\n}\n\nfunction durableScopeSql(): { clause: string; args: string[] } {\n const scopes = configuredIntegrationDurableDispatchScopes();\n if (scopes === null) return { clause: \"\", args: [] };\n if (scopes.length === 0) return { clause: \" AND 1 = 0\", args: [] };\n\n const clauses: string[] = [];\n const args: string[] = [];\n for (const scope of scopes) {\n if (scope.value === \"*\") {\n clauses.push(\"platform = ?\");\n args.push(scope.platform);\n continue;\n }\n if (scope.platform === \"slack\" && /^[A-Za-z0-9]+$/.test(scope.value)) {\n clauses.push(\n \"(platform = ? AND (external_thread_id = ? OR dispatch_scope = ? OR external_thread_id LIKE ?))\",\n );\n args.push(\n scope.platform,\n scope.value,\n scope.value,\n `%:%:${scope.value}:%`,\n );\n continue;\n }\n clauses.push(\n \"(platform = ? AND (external_thread_id = ? OR dispatch_scope = ?))\",\n );\n args.push(scope.platform, scope.value, scope.value);\n }\n return { clause: ` AND (${clauses.join(\" OR \")})`, args };\n}\n\n/**\n * One pass: find stuck tasks and re-fire the processor for each.\n * Exported for tests and for manual triggers.\n */\nexport async function retryStuckPendingTasks(\n input?: string | PendingTasksSweepOptions,\n): Promise<PendingTasksSweepResult> {\n const options: PendingTasksSweepOptions =\n typeof input === \"string\" ? { webhookBaseUrl: input } : (input ?? {});\n const baseUrl = options.webhookBaseUrl ?? activeWebhookBaseUrl;\n const limit = Math.max(\n 1,\n Math.min(500, Math.floor(options.limit ?? DEFAULT_SWEEP_LIMIT)),\n );\n const scopeSql = options.durableOnly\n ? durableScopeSql()\n : { clause: \"\", args: [] as string[] };\n const result: PendingTasksSweepResult = {\n selected: 0,\n dispatched: 0,\n markedFailed: 0,\n skipped: 0,\n dispatchFailed: 0,\n };\n await ensurePendingTasksTable();\n const client = getDbExec();\n const now = Date.now();\n const pendingCutoff = now - PENDING_STUCK_AFTER_MS;\n const processingCutoff = now - getProcessingStuckAfterMs();\n const durableProcessingCutoff =\n now - DURABLE_BACKGROUND_PROCESSING_STUCK_AFTER_MS;\n\n let stuckRows: StuckTaskRow[];\n try {\n const { rows } = await client.execute({\n sql: `\n SELECT id, platform, external_thread_id, dispatch_scope, status, attempts, updated_at\n FROM integration_pending_tasks\n WHERE ((status = 'pending' AND created_at <= ? AND updated_at <= ?)\n OR (status = 'processing' AND (\n (last_dispatch_outcome = 'background-acknowledged'\n AND updated_at <= ?)\n OR ((last_dispatch_outcome IS NULL\n OR last_dispatch_outcome <> 'background-acknowledged')\n AND updated_at <= ?)\n )))\n ${scopeSql.clause}\n ORDER BY updated_at ASC\n LIMIT ?\n `,\n // `updated_at` is initialized to `created_at` on insert, so a genuinely\n // stuck pending row still matches on the first sweep. The retry path\n // below touches `updated_at`, which (with this predicate) keeps the row\n // from being re-selected — and re-firing the processor — on every tick.\n args: [\n pendingCutoff,\n pendingCutoff,\n durableProcessingCutoff,\n processingCutoff,\n ...scopeSql.args,\n limit,\n ],\n });\n stuckRows = rows.map((r) => ({\n id: r.id as string,\n platform: r.platform as string,\n externalThreadId: r.external_thread_id as string,\n status: r.status as string,\n attempts: Number(r.attempts ?? 0),\n updatedAt: Number(r.updated_at ?? 0),\n dispatchScope: (r.dispatch_scope as string | null) ?? null,\n }));\n tableExists = true;\n } catch (err) {\n if (!isMissingPendingTasksTableError(err)) throw err;\n if (tableExists !== false) {\n tableExists = false;\n if (process.env.DEBUG) {\n console.log(\n \"[integrations] pending-tasks retry job: table not present yet, skipping\",\n );\n }\n }\n return result;\n }\n\n stuckRows = stuckRows.filter((row) => {\n const durable = isIntegrationDurableDispatchEnabledForTask({\n platform: row.platform,\n externalThreadId: row.externalThreadId,\n platformContext: row.dispatchScope\n ? { channelId: row.dispatchScope }\n : undefined,\n });\n if (options.durableOnly && !durable) return false;\n return true;\n });\n result.selected = stuckRows.length;\n if (stuckRows.length === 0) return result;\n\n for (const row of stuckRows) {\n try {\n // Cap retries — mark failed and move on so the row stops bouncing\n // between pending and processing forever.\n if (row.attempts >= MAX_PENDING_TASK_ATTEMPTS) {\n const update = await client.execute({\n sql: `\n UPDATE integration_pending_tasks\n SET status = 'failed',\n updated_at = ?,\n error_message = COALESCE(error_message, ?),\n payload = '{}',\n external_event_key = NULL\n WHERE id = ?\n AND status = ?\n AND updated_at = ?\n `,\n args: [\n Date.now(),\n `Retry job: exceeded ${MAX_PENDING_TASK_ATTEMPTS} attempts`,\n row.id,\n row.status,\n row.updatedAt,\n ],\n });\n if (affectedRows(update) === 0) {\n result.skipped += 1;\n continue;\n }\n result.markedFailed += 1;\n console.warn(\n `[integrations] Pending task ${row.id} exceeded ${MAX_PENDING_TASK_ATTEMPTS} attempts — marking failed`,\n );\n continue;\n }\n\n // Reset stuck `processing` rows back to `pending` so the processor's\n // atomic claim (which only matches pending) can re-acquire it.\n // Without this, processing rows stay stuck forever.\n // For pending rows, just touch updated_at to avoid re-firing every tick.\n const newStatus = row.status === \"processing\" ? \"pending\" : row.status;\n const update = await client.execute({\n sql: `\n UPDATE integration_pending_tasks\n SET status = ?, updated_at = ?\n WHERE id = ?\n AND status = ?\n AND updated_at = ?\n `,\n args: [newStatus, Date.now(), row.id, row.status, row.updatedAt],\n });\n if (affectedRows(update) === 0) {\n result.skipped += 1;\n continue;\n }\n\n const outcome = await dispatchPendingIntegrationTask({\n taskId: row.id,\n task: {\n platform: row.platform,\n externalThreadId: row.externalThreadId,\n platformContext: row.dispatchScope\n ? { channelId: row.dispatchScope }\n : undefined,\n },\n baseUrl,\n portableSettleMs: 1_000,\n });\n if (outcome === \"failed\") result.dispatchFailed += 1;\n else result.dispatched += 1;\n } catch (err) {\n result.dispatchFailed += 1;\n console.error(\n `[integrations] Failed to retry pending task ${row.id}:`,\n err,\n );\n }\n }\n return result;\n}\n\nfunction getProcessingStuckAfterMs(): number {\n if (\n process.env.NETLIFY ||\n process.env.AWS_LAMBDA_FUNCTION_NAME ||\n process.env.VERCEL ||\n \"__cf_env\" in globalThis\n ) {\n return SERVERLESS_PROCESSING_STUCK_AFTER_MS;\n }\n return DEFAULT_PROCESSING_STUCK_AFTER_MS;\n}\n\n/**\n * Start the periodic retry loop. Safe to call multiple times — second call\n * is a no-op.\n */\nexport function startPendingTasksRetryJob(options?: {\n webhookBaseUrl?: string;\n}): void {\n if (retryInterval) return;\n activeWebhookBaseUrl = options?.webhookBaseUrl;\n\n // Stagger the first run a bit so we don't hammer the DB immediately on boot.\n initialTimer = setTimeout(() => {\n void retryStuckPendingTasks().catch((err) => {\n console.error(\"[integrations] Pending-tasks retry job error:\", err);\n });\n }, 10_000);\n unrefTimer(initialTimer);\n\n retryInterval = setInterval(() => {\n void retryStuckPendingTasks().catch((err) => {\n console.error(\"[integrations] Pending-tasks retry job error:\", err);\n });\n }, RETRY_INTERVAL_MS);\n unrefTimer(retryInterval);\n\n if (process.env.DEBUG) {\n console.log(\n `[integrations] Pending-tasks retry job started (every ${\n RETRY_INTERVAL_MS / 1000\n }s)`,\n );\n }\n}\n\n/** Stop the retry loop. */\nexport function stopPendingTasksRetryJob(): void {\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n if (retryInterval) {\n clearInterval(retryInterval);\n retryInterval = null;\n }\n activeWebhookBaseUrl = undefined;\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n (timer as unknown as { unref?: () => void }).unref?.();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pending-tasks-retry-job.js","sourceRoot":"","sources":["../../src/integrations/pending-tasks-retry-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec } from \"../db/client.js\";\nimport { hasActiveIntegrationCampaign } from \"./integration-campaigns-store.js\";\nimport {\n configuredIntegrationDurableDispatchScopes,\n dispatchPendingIntegrationTask,\n isIntegrationDurableDispatchEnabledForTask,\n} from \"./integration-durable-dispatch.js\";\nimport {\n ensurePendingTasksTable,\n MAX_PENDING_TASK_ATTEMPTS,\n} from \"./pending-tasks-store.js\";\n\n/**\n * Retries stuck integration webhook tasks.\n *\n * The integration webhook flow enqueues work into `integration_pending_tasks`\n * (see `pending-tasks-store.ts`) and then fires a self-webhook to the\n * `/_agent-native/integrations/process-task` endpoint to drain the queue.\n * If that initial dispatch is lost (e.g. transient network blip), the\n * row stays in `pending` forever. Likewise, if the processor is killed mid-\n * processing (function timeout, container shutdown), a row can remain in\n * `processing` forever.\n *\n * The in-process fallback runs every 60s. Durable deployments also invoke the\n * same bounded sweep from an external scheduler so recovery does not depend on\n * a serverless process remaining alive.\n *\n * Each sweep re-fires the processor endpoint for tasks that\n * look stuck:\n * - status='pending' AND created_at older than 90s (initial dispatch lost)\n * - status='processing' AND updated_at older than the host-specific\n * function budget (75s on serverless, 5min elsewhere)\n *\n * Retries are capped at MAX_ATTEMPTS attempts; after that the row is marked\n * `failed` permanently so it stops being retried.\n *\n * If the `integration_pending_tasks` table does not yet exist (e.g. older\n * deploy that hasn't run the new webhook flow), this job no-ops silently\n * rather than spamming logs.\n */\n\nconst RETRY_INTERVAL_MS = 60_000;\n/** Tasks pending longer than this are considered stuck on initial dispatch */\nconst PENDING_STUCK_AFTER_MS = 90_000;\n/** Tasks \"processing\" longer than this are considered killed mid-flight. */\nconst DEFAULT_PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\nconst SERVERLESS_PROCESSING_STUCK_AFTER_MS = 75_000;\nconst DURABLE_BACKGROUND_PROCESSING_STUCK_AFTER_MS = 16 * 60 * 1000;\n/** After this many attempts we give up and mark the task failed */\nconst DEFAULT_SWEEP_LIMIT = 100;\n\nlet retryInterval: ReturnType<typeof setInterval> | null = null;\nlet initialTimer: ReturnType<typeof setTimeout> | null = null;\nlet activeWebhookBaseUrl: string | undefined;\n/**\n * Whether the table exists. Cached after first probe so we don't log every\n * minute when the queue isn't in use yet on a given deployment.\n */\nlet tableExists: boolean | null = null;\n\ninterface StuckTaskRow {\n id: string;\n platform: string;\n externalThreadId: string;\n status: string;\n attempts: number;\n updatedAt: number;\n dispatchScope: string | null;\n}\n\nexport interface PendingTasksSweepResult {\n selected: number;\n dispatched: number;\n markedFailed: number;\n skipped: number;\n dispatchFailed: number;\n}\n\nexport interface PendingTasksSweepOptions {\n webhookBaseUrl?: string;\n limit?: number;\n durableOnly?: boolean;\n}\n\nfunction affectedRows(result: unknown): number {\n return Number(\n (result as { rowsAffected?: number }).rowsAffected ??\n (result as { rowCount?: number }).rowCount ??\n 0,\n );\n}\n\nfunction isMissingPendingTasksTableError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return /no such table|relation .* does not exist|undefined_table/i.test(\n message,\n );\n}\n\nfunction durableScopeSql(): { clause: string; args: string[] } {\n const scopes = configuredIntegrationDurableDispatchScopes();\n if (scopes === null) return { clause: \"\", args: [] };\n if (scopes.length === 0) return { clause: \" AND 1 = 0\", args: [] };\n\n const clauses: string[] = [];\n const args: string[] = [];\n for (const scope of scopes) {\n if (scope.value === \"*\") {\n clauses.push(\"platform = ?\");\n args.push(scope.platform);\n continue;\n }\n if (scope.platform === \"slack\" && /^[A-Za-z0-9]+$/.test(scope.value)) {\n clauses.push(\n \"(platform = ? AND (external_thread_id = ? OR dispatch_scope = ? OR external_thread_id LIKE ?))\",\n );\n args.push(\n scope.platform,\n scope.value,\n scope.value,\n `%:%:${scope.value}:%`,\n );\n continue;\n }\n clauses.push(\n \"(platform = ? AND (external_thread_id = ? OR dispatch_scope = ?))\",\n );\n args.push(scope.platform, scope.value, scope.value);\n }\n return { clause: ` AND (${clauses.join(\" OR \")})`, args };\n}\n\n/**\n * One pass: find stuck tasks and re-fire the processor for each.\n * Exported for tests and for manual triggers.\n */\nexport async function retryStuckPendingTasks(\n input?: string | PendingTasksSweepOptions,\n): Promise<PendingTasksSweepResult> {\n const options: PendingTasksSweepOptions =\n typeof input === \"string\" ? { webhookBaseUrl: input } : (input ?? {});\n const baseUrl = options.webhookBaseUrl ?? activeWebhookBaseUrl;\n const limit = Math.max(\n 1,\n Math.min(500, Math.floor(options.limit ?? DEFAULT_SWEEP_LIMIT)),\n );\n const scopeSql = options.durableOnly\n ? durableScopeSql()\n : { clause: \"\", args: [] as string[] };\n const result: PendingTasksSweepResult = {\n selected: 0,\n dispatched: 0,\n markedFailed: 0,\n skipped: 0,\n dispatchFailed: 0,\n };\n await ensurePendingTasksTable();\n const client = getDbExec();\n const now = Date.now();\n const pendingCutoff = now - PENDING_STUCK_AFTER_MS;\n const processingCutoff = now - getProcessingStuckAfterMs();\n const durableProcessingCutoff =\n now - DURABLE_BACKGROUND_PROCESSING_STUCK_AFTER_MS;\n\n let stuckRows: StuckTaskRow[];\n try {\n const { rows } = await client.execute({\n sql: `\n SELECT id, platform, external_thread_id, dispatch_scope, status, attempts, updated_at\n FROM integration_pending_tasks\n WHERE ((status = 'pending' AND created_at <= ? AND updated_at <= ?)\n OR (status = 'processing' AND (\n (last_dispatch_outcome = 'background-acknowledged'\n AND updated_at <= ?)\n OR ((last_dispatch_outcome IS NULL\n OR last_dispatch_outcome <> 'background-acknowledged')\n AND updated_at <= ?)\n )))\n ${scopeSql.clause}\n ORDER BY updated_at ASC\n LIMIT ?\n `,\n // `updated_at` is initialized to `created_at` on insert, so a genuinely\n // stuck pending row still matches on the first sweep. The retry path\n // below touches `updated_at`, which (with this predicate) keeps the row\n // from being re-selected — and re-firing the processor — on every tick.\n args: [\n pendingCutoff,\n pendingCutoff,\n durableProcessingCutoff,\n processingCutoff,\n ...scopeSql.args,\n limit,\n ],\n });\n stuckRows = rows.map((r) => ({\n id: r.id as string,\n platform: r.platform as string,\n externalThreadId: r.external_thread_id as string,\n status: r.status as string,\n attempts: Number(r.attempts ?? 0),\n updatedAt: Number(r.updated_at ?? 0),\n dispatchScope: (r.dispatch_scope as string | null) ?? null,\n }));\n tableExists = true;\n } catch (err) {\n if (!isMissingPendingTasksTableError(err)) throw err;\n if (tableExists !== false) {\n tableExists = false;\n if (process.env.DEBUG) {\n console.log(\n \"[integrations] pending-tasks retry job: table not present yet, skipping\",\n );\n }\n }\n return result;\n }\n\n stuckRows = stuckRows.filter((row) => {\n const durable = isIntegrationDurableDispatchEnabledForTask({\n platform: row.platform,\n externalThreadId: row.externalThreadId,\n platformContext: row.dispatchScope\n ? { channelId: row.dispatchScope }\n : undefined,\n });\n if (options.durableOnly && !durable) return false;\n return true;\n });\n result.selected = stuckRows.length;\n if (stuckRows.length === 0) return result;\n\n for (const row of stuckRows) {\n try {\n if (\n row.status === \"processing\" &&\n (await hasActiveIntegrationCampaign(row.id))\n ) {\n result.skipped += 1;\n continue;\n }\n // Cap retries — mark failed and move on so the row stops bouncing\n // between pending and processing forever.\n if (row.attempts >= MAX_PENDING_TASK_ATTEMPTS) {\n const update = await client.execute({\n sql: `\n UPDATE integration_pending_tasks\n SET status = 'failed',\n updated_at = ?,\n error_message = COALESCE(error_message, ?),\n payload = '{}',\n external_event_key = NULL\n WHERE id = ?\n AND status = ?\n AND updated_at = ?\n `,\n args: [\n Date.now(),\n `Retry job: exceeded ${MAX_PENDING_TASK_ATTEMPTS} attempts`,\n row.id,\n row.status,\n row.updatedAt,\n ],\n });\n if (affectedRows(update) === 0) {\n result.skipped += 1;\n continue;\n }\n result.markedFailed += 1;\n console.warn(\n `[integrations] Pending task ${row.id} exceeded ${MAX_PENDING_TASK_ATTEMPTS} attempts — marking failed`,\n );\n continue;\n }\n\n // Reset stuck `processing` rows back to `pending` so the processor's\n // atomic claim (which only matches pending) can re-acquire it.\n // Without this, processing rows stay stuck forever.\n // For pending rows, just touch updated_at to avoid re-firing every tick.\n const newStatus = row.status === \"processing\" ? \"pending\" : row.status;\n const update = await client.execute({\n sql: `\n UPDATE integration_pending_tasks\n SET status = ?, updated_at = ?\n WHERE id = ?\n AND status = ?\n AND updated_at = ?\n `,\n args: [newStatus, Date.now(), row.id, row.status, row.updatedAt],\n });\n if (affectedRows(update) === 0) {\n result.skipped += 1;\n continue;\n }\n\n const outcome = await dispatchPendingIntegrationTask({\n taskId: row.id,\n task: {\n platform: row.platform,\n externalThreadId: row.externalThreadId,\n platformContext: row.dispatchScope\n ? { channelId: row.dispatchScope }\n : undefined,\n },\n baseUrl,\n portableSettleMs: 1_000,\n });\n if (outcome === \"failed\") result.dispatchFailed += 1;\n else result.dispatched += 1;\n } catch (err) {\n result.dispatchFailed += 1;\n console.error(\n `[integrations] Failed to retry pending task ${row.id}:`,\n err,\n );\n }\n }\n return result;\n}\n\nfunction getProcessingStuckAfterMs(): number {\n if (\n process.env.NETLIFY ||\n process.env.AWS_LAMBDA_FUNCTION_NAME ||\n process.env.VERCEL ||\n \"__cf_env\" in globalThis\n ) {\n return SERVERLESS_PROCESSING_STUCK_AFTER_MS;\n }\n return DEFAULT_PROCESSING_STUCK_AFTER_MS;\n}\n\n/**\n * Start the periodic retry loop. Safe to call multiple times — second call\n * is a no-op.\n */\nexport function startPendingTasksRetryJob(options?: {\n webhookBaseUrl?: string;\n}): void {\n if (retryInterval) return;\n activeWebhookBaseUrl = options?.webhookBaseUrl;\n\n // Stagger the first run a bit so we don't hammer the DB immediately on boot.\n initialTimer = setTimeout(() => {\n void retryStuckPendingTasks().catch((err) => {\n console.error(\"[integrations] Pending-tasks retry job error:\", err);\n });\n }, 10_000);\n unrefTimer(initialTimer);\n\n retryInterval = setInterval(() => {\n void retryStuckPendingTasks().catch((err) => {\n console.error(\"[integrations] Pending-tasks retry job error:\", err);\n });\n }, RETRY_INTERVAL_MS);\n unrefTimer(retryInterval);\n\n if (process.env.DEBUG) {\n console.log(\n `[integrations] Pending-tasks retry job started (every ${\n RETRY_INTERVAL_MS / 1000\n }s)`,\n );\n }\n}\n\n/** Stop the retry loop. */\nexport function stopPendingTasksRetryJob(): void {\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n if (retryInterval) {\n clearInterval(retryInterval);\n retryInterval = null;\n }\n activeWebhookBaseUrl = undefined;\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n (timer as unknown as { unref?: () => void }).unref?.();\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"AA6CA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AA0HzD,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EAK1B,MAAM,YAAY,CAAC;AAYpB,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAyM9D,eAAO,MAAM,sCAAsC;uBACrC,OAAO;;;uBACP,UAAU;;;uBACV,UAAU;;;uBACV,iBAAiB;;;uBACjB,SAAS;;;uBACT,aAAa;;;uBACb,OAAO;;EAIlB,CAAC;AAEJ,eAAO,MAAM,gCAAgC,0GAE5C,CAAC;AAEF,wBAAgB,gCAAgC,IAAI,eAAe,EAAE,CAEpE;AAUD,KAAK,yBAAyB,GAAG;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAgCF,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsFlC;AAmOD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,yBAAyB,GAClC,cAAc,CAklFhB;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,gBAA6B,CAAC"}
|