Skip to content

Commit 4736c58

Browse files
authored
fix: Prevent promotion filtering to exceed psql limits (#13540)
* fix(): Prevent promotion filtering to exceed psql limits * Create sour-rockets-grin.md
1 parent aa7ea4d commit 4736c58

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

.changeset/sour-rockets-grin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@medusajs/promotion": patch
3+
---
4+
5+
fix(): Prevent promotion filtering to exceed psql limits

packages/modules/promotion/integration-tests/__tests__/services/promotion-module/compute-actions.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ moduleIntegrationTestRunner({
353353
value: 100,
354354
target_rules: [
355355
{
356-
attribute: "product.id",
356+
attribute: "items.product.id",
357357
operator: "eq",
358358
values: ["prod_tshirt0"], // Only applies to product 0
359359
},

packages/modules/promotion/src/services/promotion-module.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,10 @@ export default class PromotionModuleService
466466

467467
if (!preventAutoPromotions) {
468468
const rulePrefilteringFilters =
469-
buildPromotionRuleQueryFilterFromContext(applicationContext)
469+
await buildPromotionRuleQueryFilterFromContext(
470+
applicationContext,
471+
sharedContext
472+
)
470473

471474
let prefilteredAutomaticPromotionIds: string[] = []
472475

packages/modules/promotion/src/utils/compute-actions/build-promotion-rule-query-filter-from-context.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import {
22
ComputeActionContext,
33
ComputeActionItemLine,
44
ComputeActionShippingLine,
5+
Context,
56
DAL,
67
PromotionTypes,
78
} from "@medusajs/framework/types"
89
import { flattenObjectToKeyValuePairs } from "@medusajs/framework/utils"
9-
import { raw } from "@mikro-orm/postgresql"
10+
import { raw, SqlEntityManager } from "@mikro-orm/postgresql"
1011

1112
/**
1213
* Builds a query filter for promotion rules based on the context.
@@ -17,9 +18,10 @@ import { raw } from "@mikro-orm/postgresql"
1718
* @param context
1819
* @returns
1920
*/
20-
export function buildPromotionRuleQueryFilterFromContext(
21-
context: PromotionTypes.ComputeActionContext
22-
): DAL.FilterQuery<any> | null {
21+
export async function buildPromotionRuleQueryFilterFromContext(
22+
context: PromotionTypes.ComputeActionContext,
23+
sharedContext: Context
24+
): Promise<DAL.FilterQuery<any> | null> {
2325
const {
2426
items = [],
2527
shipping_methods: shippingMethods = [],
@@ -67,6 +69,33 @@ export function buildPromotionRuleQueryFilterFromContext(
6769
})
6870
})
6971

72+
// count the number of attributes in the map
73+
const numberOfAttributes = attributeValueMap.size
74+
if (numberOfAttributes > 10) {
75+
const manager = (sharedContext.transactionManager ??
76+
sharedContext.manager) as SqlEntityManager
77+
const knex = manager.getKnex()
78+
79+
const { rows } = await knex.raw(
80+
`
81+
SELECT DISTINCT attribute
82+
FROM promotion_rule
83+
WHERE deleted_at IS NULL
84+
`
85+
)
86+
87+
const dbAvailableAttributes = new Set(
88+
rows.map(({ attribute }) => attribute)
89+
)
90+
91+
// update the attribute in the map to remove the one that are not in the db
92+
attributeValueMap.forEach((valueSet, attribute) => {
93+
if (!dbAvailableAttributes.has(attribute)) {
94+
attributeValueMap.delete(attribute)
95+
}
96+
})
97+
}
98+
7099
// Build conditions for a NOT EXISTS subquery to exclude promotions with unsatisfiable rules
71100
const sqlConditions: string[] = []
72101

0 commit comments

Comments
 (0)