chore(orchestration): serialize error (#6967)

This commit is contained in:
Carlos R. L. Rodrigues authored and GitHub committed 2024-04-06 11:22:48 +02:00
1 parent 232322d035
commit d333db0842
9 files changed
+87 -35

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/orchestration": patch
---
Serialize orchestrator error
@@ -326,7 +326,7 @@ medusaIntegrationTestRunner({
{ {
action: "find-one-or-any-region", action: "find-one-or-any-region",
handlerType: "invoke", handlerType: "invoke",
error: new Error("No regions found"), error: expect.objectContaining({ message: "No regions found" }),
}, },
]) ])
}) })
@@ -417,9 +417,9 @@ medusaIntegrationTestRunner({
{ {
action: "confirm-inventory-step", action: "confirm-inventory-step",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
"Some variant does not have the required inventory" message: "Some variant does not have the required inventory",
), }),
}, },
]) ])
}) })
@@ -441,9 +441,9 @@ medusaIntegrationTestRunner({
{ {
action: "find-sales-channel", action: "find-sales-channel",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Unable to assign cart to disabled Sales Channel: Webshop` message: `Unable to assign cart to disabled Sales Channel: Webshop`,
), }),
}, },
]) ])
}) })
@@ -471,7 +471,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed to create cart`), error: expect.objectContaining({
message: `Failed to create cart`,
}),
}, },
]) ])
@@ -508,7 +510,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed to create cart`), error: expect.objectContaining({
message: `Failed to create cart`,
}),
}, },
]) ])
@@ -705,9 +709,9 @@ medusaIntegrationTestRunner({
{ {
action: "get-variant-price-sets", action: "get-variant-price-sets",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Variants with IDs ${product.variants[0].id} do not have a price` message: `Variants with IDs ${product.variants[0].id} do not have a price`,
), }),
}, },
]) ])
}) })
@@ -734,7 +738,9 @@ medusaIntegrationTestRunner({
{ {
action: "validate-variants-exist", action: "validate-variants-exist",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Variants with IDs prva_foo do not exist`), error: expect.objectContaining({
message: `Variants with IDs prva_foo do not exist`,
}),
}, },
]) ])
}) })
@@ -975,7 +981,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed to update something after line items`), error: expect.objectContaining({
message: `Failed to update something after line items`,
}),
}, },
]) ])
@@ -1064,9 +1072,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Failed to do something after deleting line items` message: `Failed to do something after deleting line items`,
), }),
}, },
]) ])
@@ -1178,9 +1186,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Failed to do something after linking cart and payment collection` message: `Failed to do something after linking cart and payment collection`,
), }),
}, },
]) ])
@@ -1353,9 +1361,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Failed to do something after updating payment collections` message: `Failed to do something after updating payment collections`,
), }),
}, },
]) ])
@@ -1807,9 +1815,9 @@ medusaIntegrationTestRunner({
expect(errors).toEqual([ expect(errors).toEqual([
{ {
action: "get-shipping-option-price-sets", action: "get-shipping-option-price-sets",
error: new Error( error: expect.objectContaining({
`Shipping options with IDs ${shippingOption.id} do not have a price` message: `Shipping options with IDs ${shippingOption.id} do not have a price`,
), }),
handlerType: "invoke", handlerType: "invoke",
}, },
]) ])
@@ -110,9 +110,9 @@ medusaIntegrationTestRunner({
{ {
action: "throw", action: "throw",
handlerType: "invoke", handlerType: "invoke",
error: new Error( error: expect.objectContaining({
`Failed to do something after creating payment sessions` message: `Failed to do something after creating payment sessions`,
), }),
}, },
]) ])
@@ -66,7 +66,7 @@ describe("CreateInventoryItem workflow", function () {
{ {
action: "fail_step", action: "fail_step",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed`), error: expect.objectContaining({ message: `Failed` }),
}, },
]) ])
@@ -89,7 +89,9 @@ describe.skip("CreateProduct workflow", function () {
{ {
action: "fail_step", action: "fail_step",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed to create products`), error: expect.objectContaining({
message: `Failed to create products`,
}),
}, },
]) ])
@@ -1,9 +1,9 @@
import { WorkflowTypes } from "@medusajs/types"
import { import {
Handlers, Handlers,
updateProducts, updateProducts,
UpdateProductsActions, UpdateProductsActions,
} from "@medusajs/core-flows" } from "@medusajs/core-flows"
import { WorkflowTypes } from "@medusajs/types"
import { pipe } from "@medusajs/workflows-sdk" import { pipe } from "@medusajs/workflows-sdk"
import path from "path" import path from "path"
@@ -86,7 +86,9 @@ describe.skip("UpdateProduct workflow", function () {
{ {
action: "fail_step", action: "fail_step",
handlerType: "invoke", handlerType: "invoke",
error: new Error(`Failed to update products`), error: expect.objectContaining({
message: `Failed to update products`,
}),
}, },
]) ])
@@ -45,3 +45,30 @@ export class TransactionTimeoutError extends Error {
this.name = "TransactionTimeoutError" this.name = "TransactionTimeoutError"
} }
} }
export function serializeError(error) {
const serialized = {
message: error.message,
name: error.name,
stack: error.stack,
}
Object.getOwnPropertyNames(error).forEach((key) => {
// eslint-disable-next-line no-prototype-builtins
if (!serialized.hasOwnProperty(key)) {
serialized[key] = error[key]
}
})
return serialized
}
export function isErrorLike(value) {
return (
!!value &&
typeof value === "object" &&
"name" in value &&
"message" in value &&
"stack" in value
)
}
@@ -16,7 +16,9 @@ import {
import { MedusaError, promiseAll, TransactionStepState } from "@medusajs/utils" import { MedusaError, promiseAll, TransactionStepState } from "@medusajs/utils"
import { EventEmitter } from "events" import { EventEmitter } from "events"
import { import {
isErrorLike,
PermanentStepFailureError, PermanentStepFailureError,
serializeError,
TransactionStepTimeoutError, TransactionStepTimeoutError,
TransactionTimeoutError, TransactionTimeoutError,
} from "./errors" } from "./errors"
@@ -479,6 +481,10 @@ export class TransactionOrchestrator extends EventEmitter {
): Promise<void> { ): Promise<void> {
step.failures++ step.failures++
if (isErrorLike(error)) {
error = serializeError(error)
}
if ( if (
!isTimeout && !isTimeout &&
step.getStates().status !== TransactionStepStatus.PERMANENT_FAILURE step.getStates().status !== TransactionStepStatus.PERMANENT_FAILURE
@@ -1,6 +1,6 @@
import { createStep } from "../create-step" import { createStep } from "../create-step"
import { StepResponse } from "../helpers"
import { createWorkflow } from "../create-workflow" import { createWorkflow } from "../create-workflow"
import { StepResponse } from "../helpers"
import { transform } from "../transform" import { transform } from "../transform"
describe("Workflow composer", () => { describe("Workflow composer", () => {
@@ -31,7 +31,9 @@ describe("Workflow composer", () => {
{ {
action: "step2", action: "step2",
handlerType: "invoke", handlerType: "invoke",
error: new Error("step2 failed"), error: expect.objectContaining({
message: "step2 failed",
}),
}, },
expect.objectContaining({ expect.objectContaining({
message: "Cannot read properties of undefined (reading 'result')", message: "Cannot read properties of undefined (reading 'result')",