diff --git a/.changeset/little-panthers-hide.md b/.changeset/little-panthers-hide.md new file mode 100644 index 0000000000..275b5df4eb --- /dev/null +++ b/.changeset/little-panthers-hide.md @@ -0,0 +1,5 @@ +--- +"@medusajs/core-flows": patch +--- + +chore: Add locks to order edit flows diff --git a/packages/core/core-flows/src/order/workflows/order-edit/begin-order-edit.ts b/packages/core/core-flows/src/order/workflows/order-edit/begin-order-edit.ts index d6d737ba7f..4e0ae0c63e 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/begin-order-edit.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/begin-order-edit.ts @@ -11,6 +11,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { createOrderChangeStep } from "../../steps/create-order-change" import { throwIfOrderIsCancelled } from "../../utils/order-validation" import { fieldsToRefreshOrderEdit } from "./utils/fields" @@ -79,6 +80,12 @@ export const beginOrderEditOrderWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -106,6 +113,10 @@ export const beginOrderEditOrderWorkflow = createWorkflow( const orderChange = createOrderChangeStep(orderChangeInput) + releaseLockStep({ + key: input.order_id, + }) + return new WorkflowResponse(orderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/cancel-begin-order-edit.ts b/packages/core/core-flows/src/order/workflows/order-edit/cancel-begin-order-edit.ts index da3608180e..846aa2e8df 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/cancel-begin-order-edit.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/cancel-begin-order-edit.ts @@ -12,6 +12,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { emitEventStep, useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { deleteOrderChangesStep, deleteOrderShippingMethods } from "../../steps" import { throwIfIsCancelled, @@ -102,6 +103,12 @@ export const cancelBeginOrderEditWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowData { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -160,5 +167,9 @@ export const cancelBeginOrderEditWorkflow = createWorkflow( data: eventData, }) ) + + releaseLockStep({ + key: input.order_id, + }) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts b/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts index 2c3a88260a..183023a71e 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts @@ -23,6 +23,7 @@ import { requiredOrderFieldsForInventoryConfirmation, } from "../../../cart/utils/prepare-confirm-inventory-input" import { emitEventStep, useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { deleteReservationsByLineItemsStep } from "../../../reservation" import { previewOrderChangeStep } from "../../steps" import { confirmOrderChanges } from "../../steps/confirm-order-changes" @@ -120,6 +121,12 @@ export const confirmOrderEditRequestWorkflow = createWorkflow( function ( input: ConfirmOrderEditRequestWorkflowInput ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -286,6 +293,10 @@ export const confirmOrderEditRequestWorkflow = createWorkflow( data: eventData, }) + releaseLockStep({ + key: input.order_id, + }) + return new WorkflowResponse(orderPreview) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/create-order-edit-shipping-method.ts b/packages/core/core-flows/src/order/workflows/order-edit/create-order-edit-shipping-method.ts index ccaae376bb..e154327523 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/create-order-edit-shipping-method.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/create-order-edit-shipping-method.ts @@ -15,6 +15,7 @@ import { } from "@medusajs/framework/workflows-sdk" import { pricingContextResult } from "../../../cart/utils/schemas" import { useRemoteQueryStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep } from "../../steps" import { createOrderShippingMethods } from "../../steps/create-order-shipping-methods" import { @@ -113,11 +114,11 @@ export const createOrderEditShippingMethodWorkflowId = * @summary * * Create a shipping method for an order edit. - * + * * @property hooks.setPricingContext - This hook is executed before the shipping method is created. You can consume this hook to return any custom context useful for the prices retrieval of the shipping method's option. - * + * * For example, assuming you have the following custom pricing rule: - * + * * ```json * { * "attribute": "location_id", @@ -125,13 +126,13 @@ export const createOrderEditShippingMethodWorkflowId = * "value": "sloc_123", * } * ``` - * + * * You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation: - * + * * ```ts * import { createOrderEditShippingMethodWorkflow } from "@medusajs/medusa/core-flows"; * import { StepResponse } from "@medusajs/workflows-sdk"; - * + * * createOrderEditShippingMethodWorkflow.hooks.setPricingContext(( * { order, shipping_option_id, additional_data }, { container } * ) => { @@ -140,13 +141,13 @@ export const createOrderEditShippingMethodWorkflowId = * }); * }); * ``` - * + * * The price of the shipping method's option will now be retrieved using the context you return. - * + * * :::note - * + * * Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation. - * + * * ::: */ export const createOrderEditShippingMethodWorkflow = createWorkflow( @@ -154,6 +155,12 @@ export const createOrderEditShippingMethodWorkflow = createWorkflow( function ( input: CreateOrderEditShippingMethodWorkflowInput & AdditionalData ) { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const order: OrderDTO = useRemoteQueryStep({ entry_point: "orders", fields: ["id", "status", "currency_code", "canceled_at"], @@ -274,11 +281,16 @@ export const createOrderEditShippingMethodWorkflow = createWorkflow( input: [orderChangeActionInput], }) - return new WorkflowResponse( - previewOrderChangeStep(order.id) as OrderPreviewDTO, - { - hooks: [setPricingContext] as const, - } - ) + const previewOrderChange = previewOrderChangeStep( + order.id + ) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange, { + hooks: [setPricingContext] as const, + }) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/order-edit-add-new-item.ts b/packages/core/core-flows/src/order/workflows/order-edit/order-edit-add-new-item.ts index 525123318f..6673479a7c 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/order-edit-add-new-item.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/order-edit-add-new-item.ts @@ -13,16 +13,17 @@ import { WorkflowResponse, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep } from "../../steps/preview-order-change" import { throwIfIsCancelled, throwIfOrderChangeIsNotActive, } from "../../utils/order-validation" import { addOrderLineItemsWorkflow } from "../add-line-items" +import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview" import { createOrderChangeActionsWorkflow } from "../create-order-change-actions" import { updateOrderTaxLinesWorkflow } from "../update-tax-lines" import { fieldsToRefreshOrderEdit } from "./utils/fields" -import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview" /** * The data to validate that new items can be added to an order edit. @@ -103,6 +104,12 @@ export const orderEditAddNewItemWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -193,6 +200,14 @@ export const orderEditAddNewItemWorkflow = createWorkflow( }, }) - return new WorkflowResponse(previewOrderChangeStep(input.order_id)) + const previewOrderChange = previewOrderChangeStep( + input.order_id + ) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/order-edit-update-item-quantity.ts b/packages/core/core-flows/src/order/workflows/order-edit/order-edit-update-item-quantity.ts index 594034e85c..f7a12b95d6 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/order-edit-update-item-quantity.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/order-edit-update-item-quantity.ts @@ -18,13 +18,14 @@ import { WorkflowResponse, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep } from "../../steps/preview-order-change" import { throwIfIsCancelled, throwIfOrderChangeIsNotActive, } from "../../utils/order-validation" -import { createOrderChangeActionsWorkflow } from "../create-order-change-actions" import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview" +import { createOrderChangeActionsWorkflow } from "../create-order-change-actions" import { fieldsToRefreshOrderEdit } from "./utils/fields" /** @@ -113,6 +114,12 @@ export const orderEditUpdateItemQuantityWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -194,6 +201,12 @@ export const orderEditUpdateItemQuantityWorkflow = createWorkflow( }, }) - return new WorkflowResponse(previewOrderChangeStep(input.order_id)) + const previewOrderChange = previewOrderChangeStep(input.order_id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-item-action.ts b/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-item-action.ts index 53805d4b7d..0bd5016f41 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-item-action.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-item-action.ts @@ -14,6 +14,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { deleteOrderChangeActionsStep, previewOrderChangeStep, @@ -128,6 +129,12 @@ export const removeItemOrderEditActionWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -172,6 +179,12 @@ export const removeItemOrderEditActionWorkflow = createWorkflow( }, }) - return new WorkflowResponse(previewOrderChangeStep(order.id)) + const previewOrderChange = previewOrderChangeStep(order.id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-shipping-method.ts b/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-shipping-method.ts index 1915dd078c..1cd5ce99d4 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-shipping-method.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/remove-order-edit-shipping-method.ts @@ -14,6 +14,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { deleteOrderShippingMethods } from "../../steps" import { deleteOrderChangeActionsStep } from "../../steps/delete-order-change-actions" import { previewOrderChangeStep } from "../../steps/preview-order-change" @@ -111,6 +112,12 @@ export const removeOrderEditShippingMethodWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderChangeResult = useQueryGraphStep({ entity: "order_change", fields: ["id", "status", "version", "actions.*"], @@ -151,6 +158,12 @@ export const removeOrderEditShippingMethodWorkflow = createWorkflow( deleteOrderShippingMethods({ ids: [dataToRemove.shippingMethodId] }) ) - return new WorkflowResponse(previewOrderChangeStep(input.order_id)) + const previewOrderChange = previewOrderChangeStep(input.order_id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts b/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts index 5ede351d17..4389d1d217 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts @@ -14,6 +14,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { emitEventStep, useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep } from "../../steps" import { updateOrderChangesStep } from "../../steps/update-order-changes" import { @@ -128,6 +129,12 @@ export const requestOrderEditRequestWorkflow = createWorkflow( function ( input: OrderEditRequestWorkflowInput ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -180,6 +187,12 @@ export const requestOrderEditRequestWorkflow = createWorkflow( data: eventData, }) - return new WorkflowResponse(previewOrderChangeStep(order.id)) + const previewOrderChange = previewOrderChangeStep(order.id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-add-item.ts b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-add-item.ts index 7213f15c78..456368ca1b 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-add-item.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-add-item.ts @@ -14,6 +14,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep, updateOrderChangeActionsStep, @@ -127,6 +128,12 @@ export const updateOrderEditAddItemWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -193,6 +200,12 @@ export const updateOrderEditAddItemWorkflow = createWorkflow( }, }) - return new WorkflowResponse(previewOrderChangeStep(order.id)) + const previewOrderChange = previewOrderChangeStep(order.id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-item-quantity.ts b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-item-quantity.ts index 09a758eb09..9335b30a69 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-item-quantity.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-item-quantity.ts @@ -14,6 +14,7 @@ import { transform, } from "@medusajs/framework/workflows-sdk" import { useQueryGraphStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { previewOrderChangeStep, updateOrderChangeActionsStep, @@ -134,6 +135,12 @@ export const updateOrderEditItemQuantityWorkflow = createWorkflow( function ( input: WorkflowData ): WorkflowResponse { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -196,6 +203,12 @@ export const updateOrderEditItemQuantityWorkflow = createWorkflow( }, }) - return new WorkflowResponse(previewOrderChangeStep(order.id)) + const previewOrderChange = previewOrderChangeStep(order.id) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange) } ) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-shipping-method.ts b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-shipping-method.ts index b5fb000ac2..6e7582e727 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-shipping-method.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/update-order-edit-shipping-method.ts @@ -18,6 +18,7 @@ import { } from "@medusajs/framework/workflows-sdk" import { pricingContextResult } from "../../../cart/utils/schemas" import { useQueryGraphStep, useRemoteQueryStep } from "../../../common" +import { acquireLockStep, releaseLockStep } from "../../../locking" import { updateOrderChangeActionsStep, updateOrderShippingMethodsStep, @@ -162,6 +163,12 @@ export const updateOrderEditShippingMethodWorkflow = createWorkflow( OrderWorkflow.UpdateOrderEditShippingMethodWorkflowInput & AdditionalData > ) { + acquireLockStep({ + key: input.order_id, + timeout: 2, + ttl: 10, + }) + const orderResult = useQueryGraphStep({ entity: "order", fields: fieldsToRefreshOrderEdit, @@ -274,11 +281,16 @@ export const updateOrderEditShippingMethodWorkflow = createWorkflow( updateOrderShippingMethodsStep([updateData.shippingMethod!]) ) - return new WorkflowResponse( - previewOrderChangeStep(input.order_id) as OrderPreviewDTO, - { - hooks: [setPricingContext] as const, - } - ) + const previewOrderChange = previewOrderChangeStep( + input.order_id + ) as OrderPreviewDTO + + releaseLockStep({ + key: input.order_id, + }) + + return new WorkflowResponse(previewOrderChange, { + hooks: [setPricingContext] as const, + }) } )