Skip to content

Fix(webhook): Corrects webhook job execution - #3

Merged
Billos merged 1 commit into
mainfrom
fix/quick-fix-to-avoid-calling-jobs-with-bad-param
Jan 8, 2026
Merged

Fix(webhook): Corrects webhook job execution#3
Billos merged 1 commit into
mainfrom
fix/quick-fix-to-avoid-calling-jobs-with-bad-param

Conversation

@Billos

@Billos Billos commented Jan 8, 2026

Copy link
Copy Markdown
Owner

Separates transaction-specific jobs from general jobs to avoid passing bad parameters to jobs that don't require them.

This ensures that only relevant jobs are triggered for transaction webhooks, preventing errors and improving overall system stability.

Summary by CodeRabbit

Release Notes

  • Improvements
    • Reorganized background job processing to separately manage transaction-specific operations from general jobs, improving system reliability and consistency in handling transactional changes.
    • Enhanced webhook handler with optimized routing for transaction-related operations through dedicated processing paths.

✏️ Tip: You can customize this high-level summary in your review settings.

Separates transaction-specific jobs from general jobs
to avoid passing bad parameters to jobs that don't require them.

This ensures that only relevant jobs are triggered for
transaction webhooks, preventing errors and improving
overall system stability.
@Billos Billos self-assigned this Jan 8, 2026
@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR refactors job enqueueing by separating transaction-based jobs from general jobs. New type definitions distinguish between transactional and non-transactional job handlers, and the webhook endpoint implements conditional logic to route jobs accordingly based on trigger type.

Changes

Cohort / File(s) Summary
Job Definition Architecture
src/queues/index.ts
Introduced TransactionJobDefinition type for transaction-scoped jobs. Updated JobDefinition to remove transactionId parameter. Split job definitions into separate jobDefinitions (UpdateAutomaticBudgets) and transactionJobDefinitions (UnbudgetedTransactions, UncategorizedTransactions) arrays. Updated exports to expose both arrays instead of aliased queues.
Webhook Endpoint Logic
src/endpoints/webhook.ts
Updated imports to use new jobDefinitions and transactionJobDefinitions. Changed WebhookTransactionBody.trigger type from string to WebhookTrigger. Added transactionTriggers array and conditional logic: if trigger is transaction-type, enqueue all transactionJobDefinitions with {job, transactionId}; independently enqueue all jobDefinitions with {job}. Replaced previous single-loop enqueueing with branched logic.

Sequence Diagram

sequenceDiagram
    participant Webhook as Webhook Handler
    participant Logic as Trigger Detection
    participant TxnQueue as Transaction<br/>Job Queue
    participant GeneralQueue as General<br/>Job Queue

    Webhook->>Logic: Receive webhook with trigger type
    alt Transaction Trigger (STORE/UPDATE/DESTROY)
        Logic->>TxnQueue: Enqueue transactionJobDefinitions<br/>payload: {job, transactionId}
    end
    Logic->>GeneralQueue: Enqueue jobDefinitions<br/>payload: {job}
    GeneralQueue-->>Webhook: Acknowledged
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

The changes span type definition restructuring and conditional enqueueing logic, requiring verification of job parameter handling, correct classification of jobs into transaction vs. general categories, and proper payload structure for each queue type.

Poem

🐰 From tangled queues to paths so clear,
Transaction jobs need not fear!
General work flows side by side,
With better types as our guide—
Clean separation, what a delight! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: separating transaction and general jobs to fix webhook job execution with correct parameters.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/queues/index.ts (2)

52-57: Critical: Transaction jobs are never registered in the jobs record.

The initialization loop only processes jobDefinitions, but transactionJobDefinitions are never registered in the jobs record. When the webhook enqueues a transaction job (e.g., UnbudgetedTransactions or UncategorizedTransactions), the worker will attempt to call jobs[job](transactionId) at line 40, but jobs[job] will be undefined, resulting in a runtime error.

🔧 Proposed fix to register transaction jobs
 for (const { job, id, init } of jobDefinitions) {
   jobs[id] = job
   if (init) {
     await init(queue)
   }
 }
+
+for (const { job, id, init } of transactionJobDefinitions) {
+  jobs[id] = job
+  if (init) {
+    await init(queue)
+  }
+}
+
 return queue

Note: This still requires addressing the type mismatch issue (see next comment).


38-45: Critical: Type mismatch between job signatures and jobs record.

The jobs record is typed as Record<string, (transactionId: string) => Promise<void>>, expecting all jobs to accept a transactionId parameter. However:

  1. JobDefinition jobs have signature () => Promise<void> (no parameters)
  2. When these are assigned to the jobs record at line 53, there's a type mismatch
  3. The worker always calls jobs[job](transactionId), passing a parameter that general jobs don't expect

While JavaScript allows extra arguments to be ignored, this creates semantic confusion and potential issues if transactionId is undefined for general jobs.

🔧 Proposed fix with union type and conditional handling
-const jobs: Record<string, (transactionId: string) => Promise<void>> = {}
+const jobs: Record<string, ((transactionId?: string) => Promise<void>) | (() => Promise<void>)> = {}

-const worker = new Worker<QueueArgs>("manager", async ({ data: { job, transactionId } }) => jobs[job](transactionId), {
+const worker = new Worker<QueueArgs>("manager", async ({ data: { job, transactionId } }) => {
+  const jobFn = jobs[job]
+  if (!jobFn) {
+    throw new Error(`Job ${job} not found`)
+  }
+  // Call with transactionId if present, otherwise call without arguments
+  return transactionId ? jobFn(transactionId) : (jobFn as () => Promise<void>)()
+}, {
   connection: env.redisConnection,
   concurrency: 1,
   removeOnComplete: { count: 5000 },
   removeOnFail: { count: 5000 },
 })

This approach:

  • Updates the jobs record type to accommodate both signatures
  • Makes the worker conditionally pass transactionId based on its presence
  • Adds error handling for missing jobs
🤖 Fix all issues with AI agents
In @src/endpoints/webhook.ts:
- Line 34: The enqueue call uses queue.add(job, { job }, { removeOnComplete:
true, removeOnFail: true }) but the QueueArgs type (QueueArgs) requires { job:
string; transactionId: string }, so transactionId is missing and will be
undefined when the worker destructures { job, transactionId } in the worker
(index.ts). Fix by either making transactionId optional in QueueArgs (change
type to { job: string; transactionId?: string } and update worker logic to
handle undefined) OR update all callers like queue.add(...) to pass a
transactionId (even null/empty string) and ensure the worker’s destructuring and
downstream code handle the provided value.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c7d4cea and 91a3cfe.

📒 Files selected for processing (2)
  • src/endpoints/webhook.ts
  • src/queues/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/endpoints/webhook.ts (4)
src/queues/index.ts (3)
  • getQueue (70-70)
  • transactionJobDefinitions (70-70)
  • jobDefinitions (70-70)
src/queues/unbudgetedTransactions.ts (1)
  • job (73-73)
src/queues/updateAutomaticBudgets.ts (1)
  • job (54-54)
src/queues/uncategorizedTransactions.ts (1)
  • job (92-92)
src/queues/index.ts (1)
src/queues/queueArgs.ts (1)
  • QueueArgs (1-1)
🔇 Additional comments (6)
src/endpoints/webhook.ts (3)

3-4: LGTM! Type safety improvement.

The import updates and type strengthening from string to WebhookTrigger improve type safety and align with the separation of transaction-specific and general jobs.

Also applies to: 9-9


16-20: LGTM!

The transactionTriggers array correctly identifies transaction-specific webhook triggers and is properly typed.


33-35: Confirm the intended behavior for general jobs running on all webhook triggers.

The general jobs (from jobDefinitions) are indeed enqueued for every webhook request, including non-transaction triggers like STORE_BUDGET, UPDATE_BUDGET, DESTROY_BUDGET, and STORE_UPDATE_BUDGET_LIMIT. Jobs like UpdateAutomaticBudgets—which fetches all budgets, reviews limits, and updates budget allocations—will execute regardless of trigger type.

This may be intentional (to keep budgets synchronized on any webhook event), but it lacks documentation. Either clarify why all jobs should run for all webhook types or add conditional logic to execute jobs only for relevant trigger types.

src/queues/index.ts (3)

10-15: Type definitions look correct for the separation intent.

The new type definitions correctly distinguish between transaction-specific jobs (requiring transactionId) and general jobs (no parameters). However, the integration with the worker and jobs record has critical issues (see subsequent comments).


17-24: Arrays are correctly defined.

The separation of UpdateAutomaticBudgets into jobDefinitions and transaction-specific jobs into transactionJobDefinitions aligns with the PR objectives.


70-70: LGTM!

The export statement correctly exposes both jobDefinitions and transactionJobDefinitions, enabling the webhook to handle them separately.

Comment thread src/endpoints/webhook.ts
}
}
for (const { id: job } of jobDefinitions) {
queue.add(job, { job }, { removeOnComplete: true, removeOnFail: true })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Type mismatch: Missing required transactionId field.

The QueueArgs type defined in src/queues/queueArgs.ts requires both job and transactionId fields: { job: string; transactionId: string }. However, general jobs are enqueued with only { job }, missing the required transactionId field.

When the worker destructures { job, transactionId } at line 40 in src/queues/index.ts, transactionId will be undefined for general jobs, which could cause runtime errors or unexpected behavior.

🔧 Potential fix options

Option 1: Make transactionId optional in QueueArgs

In src/queues/queueArgs.ts:

-export type QueueArgs = { job: string; transactionId: string }
+export type QueueArgs = { job: string; transactionId?: string }

Option 2: Pass undefined explicitly

-queue.add(job, { job }, { removeOnComplete: true, removeOnFail: true })
+queue.add(job, { job, transactionId: undefined }, { removeOnComplete: true, removeOnFail: true })

Note: This still requires adjusting the worker to handle optional transactionId.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @src/endpoints/webhook.ts at line 34, The enqueue call uses queue.add(job, {
job }, { removeOnComplete: true, removeOnFail: true }) but the QueueArgs type
(QueueArgs) requires { job: string; transactionId: string }, so transactionId is
missing and will be undefined when the worker destructures { job, transactionId
} in the worker (index.ts). Fix by either making transactionId optional in
QueueArgs (change type to { job: string; transactionId?: string } and update
worker logic to handle undefined) OR update all callers like queue.add(...) to
pass a transactionId (even null/empty string) and ensure the worker’s
destructuring and downstream code handle the provided value.

@Billos
Billos merged commit 4bade77 into main Jan 8, 2026
5 checks passed
@Billos
Billos deleted the fix/quick-fix-to-avoid-calling-jobs-with-bad-param branch January 8, 2026 12:28
@coderabbitai coderabbitai Bot mentioned this pull request Jan 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant