chore: idempotent cart operations (#13236)
* chore(core-flows): idempotent cart operations * changeset * add tests * revert * revert route * promo test * skip bugs * fix test * tests * avoid workflow name conflict * prevent nested workflow from being deleted until the top level parent finishes * remove unused setTimeout * update changeset * rm comments --------- Co-authored-by: adrien2p <adrien.deperetti@gmail.com>
This commit is contained in:
committed by
GitHub
parent
b111d01898
commit
9412669e65
@@ -54,6 +54,7 @@ createWorkflow(
|
||||
{
|
||||
name: "workflow_idempotent",
|
||||
idempotent: true,
|
||||
retentionTime: 20,
|
||||
},
|
||||
function (input) {
|
||||
step_1(input)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { isPresent } from "@medusajs/framework/utils"
|
||||
import {
|
||||
createStep,
|
||||
createWorkflow,
|
||||
StepResponse,
|
||||
WorkflowResponse,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import { isPresent } from "@medusajs/framework/utils"
|
||||
|
||||
const step_1 = createStep(
|
||||
"step_1",
|
||||
@@ -53,6 +53,7 @@ const step_3 = createStep(
|
||||
createWorkflow(
|
||||
{
|
||||
name: "workflow_sync",
|
||||
retentionTime: 20,
|
||||
idempotent: true,
|
||||
},
|
||||
function (input) {
|
||||
|
||||
@@ -177,6 +177,15 @@
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_workflow_execution_state\" ON \"workflow_execution\" (state) WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_workflow_execution_run_id",
|
||||
"columnNames": [],
|
||||
"composite": false,
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_workflow_execution_run_id\" ON \"workflow_execution\" (run_id) WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "workflow_execution_pkey",
|
||||
"columnNames": [
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20250819104213 extends Migration {
|
||||
|
||||
override async up(): Promise<void> {
|
||||
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_workflow_execution_run_id" ON "workflow_execution" (run_id) WHERE deleted_at IS NULL;`);
|
||||
}
|
||||
|
||||
override async down(): Promise<void> {
|
||||
this.addSql(`drop index if exists "IDX_workflow_execution_run_id";`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,4 +34,8 @@ export const WorkflowExecution = model
|
||||
on: ["state"],
|
||||
where: "deleted_at IS NULL",
|
||||
},
|
||||
{
|
||||
on: ["run_id"],
|
||||
where: "deleted_at IS NULL",
|
||||
},
|
||||
])
|
||||
|
||||
@@ -180,6 +180,7 @@ export class WorkflowsModuleService<
|
||||
...(restContext ?? {}),
|
||||
...(options_.context ?? {}),
|
||||
eventGroupId,
|
||||
runId: options_.runId,
|
||||
preventReleaseEvents: localPreventReleaseEvents,
|
||||
}
|
||||
|
||||
|
||||
@@ -138,8 +138,6 @@ export class InMemoryDistributedTransactionStorage
|
||||
private async deleteFromDb(data: TransactionCheckpoint) {
|
||||
await this.workflowExecutionService_.delete([
|
||||
{
|
||||
workflow_id: data.flow.modelId,
|
||||
transaction_id: data.flow.transactionId,
|
||||
run_id: data.flow.runId,
|
||||
},
|
||||
])
|
||||
@@ -223,7 +221,7 @@ export class InMemoryDistributedTransactionStorage
|
||||
TransactionState.REVERTED,
|
||||
].includes(data.flow.state)
|
||||
|
||||
const { retentionTime, idempotent } = options ?? {}
|
||||
const { retentionTime } = options ?? {}
|
||||
|
||||
await this.#preventRaceConditionExecutionIfNecessary({
|
||||
data,
|
||||
@@ -261,8 +259,13 @@ export class InMemoryDistributedTransactionStorage
|
||||
|
||||
// Optimize DB operations - only perform when necessary
|
||||
if (hasFinished) {
|
||||
if (!retentionTime && !idempotent) {
|
||||
await this.deleteFromDb(data)
|
||||
if (!retentionTime) {
|
||||
// If the workflow is nested, we cant just remove it because it would break the compensation algorithm. Instead, it will get deleted when the top level parent is deleted.
|
||||
if (!flow.metadata?.parentStepIdempotencyKey) {
|
||||
await this.deleteFromDb(data)
|
||||
} else {
|
||||
await this.saveToDb(data, retentionTime)
|
||||
}
|
||||
} else {
|
||||
await this.saveToDb(data, retentionTime)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user