feat(medusa): Rollout index engine behind feature flag (#11431)

**What**
- Add index engine feature flag
- apply it to the `store/products` end point as well as `admin/products`
- Query builder various fixes
- search capabilities on full data of every entities. The `q` search will be applied to all involved joined table for selection/where clauses

Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
Adrien de Peretti
2025-02-18 13:49:57 +00:00
committed by GitHub
co-authored by Carlos R. L. Rodrigues
parent 3b69f5a105
commit 448dbcb596
27 changed files with 881 additions and 135 deletions
@@ -1,4 +1,5 @@
import {
featureFlagRouter,
validateAndTransformBody,
validateAndTransformQuery,
} from "@medusajs/framework"
@@ -35,6 +36,7 @@ import {
CreateProduct,
CreateProductVariant,
} from "./validators"
import IndexEngineFeatureFlag from "../../../loaders/feature-flags/index-engine"
// TODO: For now we keep the files in memory, as that's how they get passed to the workflows
// This will need revisiting once we are closer to prod-ready v2, since with workflows and potentially
@@ -50,11 +52,17 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
AdminGetProductsParams,
QueryConfig.listProductQueryConfig
),
maybeApplyLinkFilter({
entryPoint: "product_sales_channel",
resourceId: "product_id",
filterableField: "sales_channel_id",
}),
(req, res, next) => {
if (featureFlagRouter.isFeatureEnabled(IndexEngineFeatureFlag.key)) {
return next()
}
return maybeApplyLinkFilter({
entryPoint: "product_sales_channel",
resourceId: "product_id",
filterableField: "sales_channel_id",
})(req, res, next)
},
maybeApplyPriceListsFilter(),
],
},
@@ -7,11 +7,33 @@ import {
refetchEntity,
} from "@medusajs/framework/http"
import { remapKeysForProduct, remapProductResponse } from "./helpers"
import IndexEngineFeatureFlag from "../../../loaders/feature-flags/index-engine"
import { featureFlagRouter } from "@medusajs/framework"
import { ContainerRegistrationKeys, isPresent } from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.AdminProductListParams>,
res: MedusaResponse<HttpTypes.AdminProductListResponse>
) => {
if (featureFlagRouter.isFeatureEnabled(IndexEngineFeatureFlag.key)) {
// TODO: These filters are not supported by the index engine yet
if (
isPresent(req.filterableFields.tags) ||
isPresent(req.filterableFields.categories)
) {
return await getProducts(req, res)
}
return await getProductsWithIndexEngine(req, res)
}
return await getProducts(req, res)
}
async function getProducts(
req: AuthenticatedMedusaRequest<HttpTypes.AdminProductListParams>,
res: MedusaResponse<HttpTypes.AdminProductListResponse>
) {
const selectFields = remapKeysForProduct(req.queryConfig.fields ?? [])
const { rows: products, metadata } = await refetchEntities(
@@ -30,6 +52,27 @@ export const GET = async (
})
}
async function getProductsWithIndexEngine(
req: AuthenticatedMedusaRequest<HttpTypes.AdminProductListParams>,
res: MedusaResponse<HttpTypes.AdminProductListResponse>
) {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: products, metadata } = await query.index({
entity: "product",
fields: req.queryConfig.fields ?? [],
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
})
res.json({
products: products.map(remapProductResponse),
count: metadata!.count,
offset: metadata!.skip,
limit: metadata!.take,
})
}
export const POST = async (
req: AuthenticatedMedusaRequest<
HttpTypes.AdminCreateProduct & AdditionalData