From a25111444a2648c28751ddfe69db6553e16d27c1 Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Thu, 18 Sep 2025 18:51:23 +0200 Subject: [PATCH] Completely remove all race condition and optimistic locking logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove webhook context tracking system (context.ts file) - Eliminate updatePaymentFromWebhook wrapper function - Simplify payment providers to use updatePaymentStatus directly - Remove all version-based optimistic locking references - Clean up webhook context parameters and metadata - Streamline codebase assuming providers don't send duplicate webhooks The payment system now operates with simple, direct updates without any race condition handling, as payment providers typically don't send duplicate webhook requests for the same event. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/providers/context.ts | 50 ---------------------------------------- src/providers/mollie.ts | 10 ++++---- src/providers/stripe.ts | 14 ++++------- src/providers/utils.ts | 24 ------------------- 4 files changed, 9 insertions(+), 89 deletions(-) delete mode 100644 src/providers/context.ts diff --git a/src/providers/context.ts b/src/providers/context.ts deleted file mode 100644 index 5809613..0000000 --- a/src/providers/context.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Request context utilities for tracking webhook vs manual operations - */ - -// Symbol for storing webhook context in the request object -const WEBHOOK_CONTEXT_SYMBOL = Symbol('billingWebhookContext') - -export interface WebhookContext { - isWebhookUpdate: boolean - provider?: string - webhookType?: string - timestamp: string - metadata?: Record -} - -/** - * Mark a request as coming from a webhook - */ -export function markRequestAsWebhook( - req: any, - provider: string, - webhookType: string = 'payment_update', - metadata?: Record -): void { - const context: WebhookContext = { - isWebhookUpdate: true, - provider, - webhookType, - timestamp: new Date().toISOString(), - metadata - } - - // Store context in request object using symbol to avoid conflicts - req[WEBHOOK_CONTEXT_SYMBOL] = context -} - -/** - * Check if a request is from a webhook - */ -export function isWebhookRequest(req: any): boolean { - const context = req[WEBHOOK_CONTEXT_SYMBOL] as WebhookContext | undefined - return context?.isWebhookUpdate === true -} - -/** - * Get webhook context from request - */ -export function getWebhookContext(req: any): WebhookContext | null { - return req[WEBHOOK_CONTEXT_SYMBOL] as WebhookContext || null -} \ No newline at end of file diff --git a/src/providers/mollie.ts b/src/providers/mollie.ts index b7af60e..b8d5440 100644 --- a/src/providers/mollie.ts +++ b/src/providers/mollie.ts @@ -6,7 +6,7 @@ import type { createMollieClient, MollieClient } from '@mollie/api-client' import { webhookResponses, findPaymentByProviderId, - updatePaymentFromWebhook, + updatePaymentStatus, updateInvoiceOnPaymentSuccess, handleWebhookError, validateProductionUrl @@ -83,15 +83,13 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & { // Map Mollie status to our status using proper type-safe mapping const status = mapMollieStatusToPaymentStatus(molliePayment.status) - // Update the payment status and provider data with webhook context - const updateSuccess = await updatePaymentFromWebhook( + // Update the payment status and provider data + const updateSuccess = await updatePaymentStatus( payload, payment.id, status, molliePayment.toPlainObject(), - pluginConfig, - 'mollie', - `payment.${molliePayment.status}` + pluginConfig ) // If payment is successful and update succeeded, update the invoice diff --git a/src/providers/stripe.ts b/src/providers/stripe.ts index 6f30d60..8269f6c 100644 --- a/src/providers/stripe.ts +++ b/src/providers/stripe.ts @@ -6,7 +6,7 @@ import type Stripe from 'stripe' import { webhookResponses, findPaymentByProviderId, - updatePaymentFromWebhook, + updatePaymentStatus, updateInvoiceOnPaymentSuccess, handleWebhookError, logWebhookEvent @@ -117,14 +117,12 @@ export const stripeProvider = (stripeConfig: StripeProviderConfig) => { timestamp: new Date().toISOString(), provider: 'stripe' } - const updateSuccess = await updatePaymentFromWebhook( + const updateSuccess = await updatePaymentStatus( payload, payment.id, status, providerData, - pluginConfig, - 'stripe', - event.type + pluginConfig ) // If payment is successful and update succeeded, update the invoice @@ -165,14 +163,12 @@ export const stripeProvider = (stripeConfig: StripeProviderConfig) => { timestamp: new Date().toISOString(), provider: 'stripe' } - const updateSuccess = await updatePaymentFromWebhook( + const updateSuccess = await updatePaymentStatus( payload, payment.id, isFullyRefunded ? 'refunded' : 'partially_refunded', providerData, - pluginConfig, - 'stripe', - event.type + pluginConfig ) if (!updateSuccess) { diff --git a/src/providers/utils.ts b/src/providers/utils.ts index 87a4051..89ff533 100644 --- a/src/providers/utils.ts +++ b/src/providers/utils.ts @@ -4,7 +4,6 @@ import type { BillingPluginConfig } from '@/plugin/config' import type { ProviderData } from './types' import { defaults } from '@/plugin/config' import { extractSlug, toPayloadId } from '@/plugin/utils' -import { markRequestAsWebhook } from './context' /** * Common webhook response utilities @@ -44,29 +43,6 @@ export async function findPaymentByProviderId( return payments.docs.length > 0 ? payments.docs[0] as Payment : null } -/** - * Update payment status from webhook with proper context tracking - */ -export async function updatePaymentFromWebhook( - payload: Payload, - paymentId: string | number, - status: Payment['status'], - providerData: ProviderData, - pluginConfig: BillingPluginConfig, - provider: string, - eventType?: string -): Promise { - // Mark the request context as webhook before updating with metadata - markRequestAsWebhook((payload as any).req, provider, 'payment_status_update', { - paymentId: paymentId.toString(), - newStatus: status, - eventType, - timestamp: new Date().toISOString() - }) - - return updatePaymentStatus(payload, paymentId, status, providerData, pluginConfig) -} - /** * Update payment status and provider data */