docs: update sanity guide + marketplace recipe to use permanentFailure (#10310)
This commit is contained in:
@@ -703,9 +703,9 @@ export const syncStep = createStep(
|
||||
const batchSize = 200
|
||||
const hasMore = true
|
||||
const offset = 0
|
||||
const filters = {
|
||||
id: input.product_ids || [],
|
||||
}
|
||||
let filters = input.product_ids ? {
|
||||
id: input.product_ids
|
||||
} : {}
|
||||
|
||||
while (hasMore) {
|
||||
const {
|
||||
@@ -719,7 +719,6 @@ export const syncStep = createStep(
|
||||
// @ts-ignore
|
||||
"sanity_product.*",
|
||||
],
|
||||
// @ts-ignore
|
||||
filters,
|
||||
pagination: {
|
||||
skip: offset,
|
||||
@@ -777,22 +776,29 @@ export const syncStep = createStep(
|
||||
|
||||
while (hasMore) {
|
||||
// ...
|
||||
await promiseAll(
|
||||
products.map(async (prod) => {
|
||||
const after = await sanityModule.upsertSyncDocument(
|
||||
"product",
|
||||
prod as ProductDTO
|
||||
)
|
||||
|
||||
upsertMap.push({
|
||||
// @ts-ignore
|
||||
before: prod.sanity_product,
|
||||
after,
|
||||
})
|
||||
|
||||
return after
|
||||
})
|
||||
)
|
||||
try {
|
||||
await promiseAll(
|
||||
products.map(async (prod) => {
|
||||
const after = await sanityModule.upsertSyncDocument(
|
||||
"product",
|
||||
prod as ProductDTO
|
||||
);
|
||||
|
||||
upsertMap.push({
|
||||
// @ts-ignore
|
||||
before: prod.sanity_product,
|
||||
after
|
||||
})
|
||||
|
||||
return after
|
||||
}),
|
||||
)
|
||||
} catch (e) {
|
||||
return StepResponse.permanentFailure(
|
||||
`An error occurred while syncing documents: ${e}`,
|
||||
upsertMap
|
||||
)
|
||||
}
|
||||
|
||||
offset += batchSize
|
||||
hasMore = offset < count
|
||||
@@ -808,7 +814,9 @@ In the `while` loop, you loop over the array of products to sync them to Sanity.
|
||||
|
||||
For each product, you upsert it into Sanity, then push its document before and after the update to the `upsertMap`. You'll learn more about its use later.
|
||||
|
||||
The step returns an instance of `StepResponse`, which must be returned by any step. It accepts as a first parameter the data to return to the workflow that executed this step.
|
||||
You also wrap the `promiseAll` function within a try-catch block. In the catch block, you invoke and return `StepResponse.permanentFailure` which indicates that the step has failed but still invokes the rollback mechanism that you'll implement in a bit. The first parameter of `permanentFailure` is the error message, and the second is the data to use in the rollback mechanism.
|
||||
|
||||
If no errors occur, the step returns an instance of `StepResponse`, which must be returned by any step. It accepts as a first parameter the data to return to the workflow that executed this step.
|
||||
|
||||
#### Add Compensation Function
|
||||
|
||||
|
||||
@@ -893,10 +893,10 @@ import {
|
||||
LinkDefinition,
|
||||
InferTypeOf,
|
||||
} from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { Modules, promiseAll } from "@medusajs/framework/utils"
|
||||
import {
|
||||
createOrdersWorkflow,
|
||||
cancelOrderWorkflow,
|
||||
createOrderWorkflow
|
||||
} from "@medusajs/medusa/core-flows"
|
||||
import MarketplaceModuleService from "../../../../modules/marketplace/service"
|
||||
import { MARKETPLACE_MODULE } from "../../../../modules/marketplace"
|
||||
@@ -1009,12 +1009,12 @@ export const vendorOrder3Highlights = [
|
||||
|
||||
```ts title="src/workflows/marketplace/create-vendor-orders/steps/create-vendor-orders.ts" highlights={vendorOrder3Highlights}
|
||||
try {
|
||||
await Promise.all(
|
||||
await promiseAll(
|
||||
vendorIds.map(async (vendorId) => {
|
||||
const items = vendorsItems[vendorId]
|
||||
const vendor = vendors.find((v) => v.id === vendorId)!
|
||||
const vendor = vendors.find(v => v.id === vendorId)!
|
||||
|
||||
const { result: childOrder } = await createOrdersWorkflow(
|
||||
const {result: childOrder} = await createOrderWorkflow(
|
||||
container
|
||||
)
|
||||
.run({
|
||||
@@ -1027,31 +1027,28 @@ try {
|
||||
|
||||
linkDefs.push({
|
||||
[MARKETPLACE_MODULE]: {
|
||||
vendor_id: vendor.id,
|
||||
vendor_id: vendor.id
|
||||
},
|
||||
[Modules.ORDER]: {
|
||||
order_id: childOrder.id,
|
||||
},
|
||||
order_id: childOrder.id
|
||||
}
|
||||
})
|
||||
})
|
||||
)
|
||||
} catch (e) {
|
||||
await Promise.all(createdOrders.map((createdOrder) => {
|
||||
return cancelOrderWorkflow(container).run({
|
||||
input: {
|
||||
order_id: createdOrder.id,
|
||||
},
|
||||
context,
|
||||
container,
|
||||
})
|
||||
}))
|
||||
|
||||
throw e
|
||||
return StepResponse.permanentFailure(
|
||||
`An error occured while creating vendor orders: ${e}`,
|
||||
{
|
||||
created_orders: createdOrders
|
||||
}
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
In this snippet, you create multiple child orders for each vendor and link the orders to the vendors.
|
||||
|
||||
You use the `promiseAll` utility imported from `@medusajs/framework/utils` that loops over an array of promises and ensures that all transactions within these promises are rolled back in case an error occurs. You also wrap `promiseAll` in a try-catch block, and in the catch block you invoke and return `StepResponse.permanentFailure` which indicates that the step has failed but still invokes the compensation function that you'll implement in a bit. The first parameter of `permanentFailure` is the error message, and the second is the data to pass to the compensation function.
|
||||
|
||||
If an error occurs, the created orders in the `createdOrders` array are canceled using Medusa's `cancelOrderWorkflow` from the `@medusajs/medusa/core-flows` package.
|
||||
|
||||
The order's data is formatted using the `prepareOrderData` function. Replace its definition with the following:
|
||||
@@ -1165,7 +1162,7 @@ const createVendorOrdersWorkflow = createWorkflow(
|
||||
(input: WorkflowInput) => {
|
||||
const { data: carts } = useQueryGraphStep({
|
||||
entity: "cart",
|
||||
fields: ["items.*"],
|
||||
fields: ["id", "items.*"],
|
||||
filters: { id: input.cart_id },
|
||||
options: {
|
||||
throwIfKeyNotFound: true,
|
||||
@@ -1179,7 +1176,7 @@ const createVendorOrdersWorkflow = createWorkflow(
|
||||
})
|
||||
|
||||
const { vendorsItems } = groupVendorItemsStep({
|
||||
cart: carts[0].id,
|
||||
cart: carts[0]
|
||||
})
|
||||
|
||||
const order = getOrderDetailWorkflow.runAsStep({
|
||||
|
||||
@@ -130,7 +130,7 @@ export const generatedEditDates = {
|
||||
"app/recipes/digital-products/page.mdx": "2024-10-03T13:07:44.147Z",
|
||||
"app/recipes/ecommerce/page.mdx": "2024-10-22T11:01:01.218Z",
|
||||
"app/recipes/integrate-ecommerce-stack/page.mdx": "2024-10-16T08:52:16.760Z",
|
||||
"app/recipes/marketplace/examples/vendors/page.mdx": "2024-10-16T08:52:24.906Z",
|
||||
"app/recipes/marketplace/examples/vendors/page.mdx": "2024-11-27T10:30:50.653Z",
|
||||
"app/recipes/marketplace/page.mdx": "2024-10-03T13:07:44.153Z",
|
||||
"app/recipes/multi-region-store/page.mdx": "2024-10-03T13:07:13.813Z",
|
||||
"app/recipes/omnichannel/page.mdx": "2024-10-03T13:07:14.384Z",
|
||||
@@ -3252,7 +3252,7 @@ export const generatedEditDates = {
|
||||
"references/types/HttpTypes/interfaces/types.HttpTypes.AdminBatchProductVariantRequest/page.mdx": "2024-11-25T17:49:26.851Z",
|
||||
"references/types/WorkflowTypes/ProductWorkflow/interfaces/types.WorkflowTypes.ProductWorkflow.ExportProductsDTO/page.mdx": "2024-11-12T09:36:24.232Z",
|
||||
"app/contribution-guidelines/admin-translations/page.mdx": "2024-11-14T08:54:15.369Z",
|
||||
"app/integrations/guides/sanity/page.mdx": "2024-11-19T10:07:24.519Z",
|
||||
"app/integrations/guides/sanity/page.mdx": "2024-11-27T10:10:12.100Z",
|
||||
"references/api_key/types/api_key.FindConfigOrder/page.mdx": "2024-11-25T17:49:28.715Z",
|
||||
"references/auth/types/auth.FindConfigOrder/page.mdx": "2024-11-25T17:49:28.887Z",
|
||||
"references/cart/types/cart.FindConfigOrder/page.mdx": "2024-11-25T17:49:29.455Z",
|
||||
|
||||
Reference in New Issue
Block a user