Skip to content

DO NOT MERGE: PLP Reference Example#267

Draft
sirugh wants to merge 10 commits into
mainfrom
plp
Draft

DO NOT MERGE: PLP Reference Example#267
sirugh wants to merge 10 commits into
mainfrom
plp

Conversation

@sirugh
Copy link
Copy Markdown
Collaborator

@sirugh sirugh commented Mar 23, 2026

Do not merge. This is a WIP/reference branch.

This PR demonstrates end-to-end PDP and PLP pre-rendering support for both ACO and ACCS sites. It can be used as a reference or basis for adopting pre-rendering in your own project. See commit history and linked PRs for further context.

What's included

PDP pre-rendering — ACO support (#265, USF-3785/3786/3770)

  • Detect site type via config['adobe-commerce-optimizer'] or AC--prefixed CS headers (getSiteType)
  • Configure category families via ACO_CATEGORY_FAMILIES env var
  • Resolve category slugs from families for PDP pre-rendering
  • Category Tree queries in actions/queries.js

PLP pre-rendering (#266, USF-3819/3834)

  • render-all-categories action + poller to pre-render all PLPs per category
  • plp-renderer directory: Handlebars templates, rendering, preview, and publish logic
  • plp-renderer/ldJson.js: generates CollectionPage JSON-LD with BreadcrumbList and ItemList
  • PLP_PRODUCTS_PER_PAGE input (default: 9)
  • Updated README and Runbook documentation

PLP block decoration fix (#268, USF-3898)

  • Aligns prerendered markup with storefront block expectations: product-list-page as root block, content wrapped in a div

PLP category product rendering fix (#270, USF-4023)

  • Includes urlPath field in the product-listing block so PLPs render the correct category's products

URL sanitization & template error handling

  • getCategoryUrl (utils.js): sanitizes each URL path segment individually via sanitizeName so double-hyphens in any segment are normalized correctly
  • renderUtils.prepareBaseTemplate: warns and returns empty string instead of throwing when the products template fetch fails

renderUtils.js — shared rendering infrastructure

Consolidates logic previously duplicated between PDP and PLP:

  • loadState / saveState / deleteState: parameterized by dataKey and filePrefix so both pollers share the same state I/O
  • processPublishedBatch: handles state updates and counters for both PDP and PLP publish flows
  • validateRequiredParams, getHtmlFilePath
  • sanitize: HTML tag allowlist with all, inline, and no modes
  • Price helpers (getProductPrice, generatePriceString), image helpers (getPrimaryImage, getImageList), getGTIN, getBrand, findDescription

categories.js — category tree module

  • BFS traversal of the ACO category tree API, handling trees of arbitrary depth when the API caps depth per call
  • getCategorySlugsFromFamilies, getCategoryMapFromFamilies, getCategoryMap, getCategories, buildBreadcrumbs
  • Shared by both fetch-all-products (ACO PDP) and render-all-categories (PLP)

fetch-all-products refactor

  • ACO support via category families
  • Parallelized pagination (CONCURRENCY=5, p-limit), capped at MAX_PRODUCTS_PER_CATEGORY=10,000 with a warning

Stability & observability improvements (#271)

Watchdog timer (check-product-changes/poller.js, render-all-categories/poller.js)
Uses Promise.race between locale processing and a watchdog promise (polled every 30s). If no render or AEM batch completes within 5 minutes, the action aborts by calling adminApi.abortProcessing() (skips draining queues) rather than burning the full timeout.

Extended timeout & memory (app.config.yaml, check-product-changes/index.js)
check-product-changes timeout extended from 1h → 3h, memory from 512 MB → 4 GB. Mutex TTL is now derived from ACTION_TIMEOUT_MS so the lock auto-expires if the runtime kills the process unexpectedly.

AEM Admin API tuning (aem.js)
BATCH_SIZE raised to 600 paths/minute to match the overlay API limit. MAX_PENDING_JOBS reduced 20 → 4 and poll interval increased 5s → 15s to reduce memory backlog at the higher batch size. abortProcessing() added for the watchdog path.

mark-up-clean-up batching
GetUrlKey GraphQL queries are batched at CATALOG_BATCH_SIZE=100 (catalog hard limit). Unpublish batches keep BATCH_SIZE=600. createBatches now accepts an optional size parameter.

Concurrent render limit (check-product-changes/poller.js)
p-limit concurrency reduced 50 → 20: at 50 concurrent renders the Commerce API returned 504s, stalling the action and triggering the watchdog.

LOCAL_FS mode (localFilesLib.js, all four actions, runners)
Set LOCAL_FS=true to redirect all aio Files I/O to ./local-data/ for running the full pipeline locally without App Builder credentials. Preview/publish still targets the site's configured overlay.

Tooling

  • tools/check-errors.sh: paginates aio rt activation list, surfaces error activations and prints full logs; wired up as /check-aio-errors Claude slash command
  • tools/get-state-csv.js: fetches and saves state CSVs for both check-product-changes and render-all-categories to local-data/
  • RUNBOOK.md: notes on long-running activations not appearing in aio rt activation list until completion; LOCAL_FS usage docs

rossbrandon and others added 7 commits March 12, 2026 13:31
Add PDP pre-render support for Commerce Optimizer

---------

Co-authored-by: Stephen <sirugh@users.noreply.github.com>
Add support for PLP pre-rendering
* Render PLPs from category base template and replace only product-list-page block

* Revert "Render PLPs from category base template and replace only product-list-page block"

This reverts commit 55394bf.

* Update product-list-page class name and wrap content in a div
Comment thread app.config.yaml Outdated
sirugh and others added 3 commits May 4, 2026 12:18
…ssing template gracefully

- getCategoryUrl: split slug into segments and run sanitizeName on each (instead of
  sanitizePath on the whole path) so double-hyphens in any segment are normalized
- renderUtils: warn and return empty string instead of throwing when template fetch fails
- Updated helix-shared-string mock and tests to cover both changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* adds local_fs capability, to debug without aio. bumps timeouts and memory

Signed-off-by: Stephen Rugh <rugh@adobe.com>

* increasing timeout to 3 hours and commenting out triggers for now

Signed-off-by: Stephen Rugh <rugh@adobe.com>

* add claude tool to summarize and check errors in activations

* batch getUrlKey GraphQL queries in mark-up-clean-up to stay within catalog 100-product limit

Passing all published SKUs in a single query fails when the catalog exceeds 100 products
(observed at 23,398 SKUs: "Product count exceeds the maximum allowed (100)"). With no
query result, every published product appears redundant and risks mass unpublishing.

Fix: split SKUs into batches of 50 (reusing createBatches/BATCH_SIZE) and fan out
requests in parallel, then merge results before the redundancy check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* add script to get the state file. add note to runbook about log availability. add watchdog exit script to exit early incase of recurring failures at commerce api (504, etc).

* Updates comments on watchdog and ensures we dont exit while publishing batches.

* Apply suggestion from @sirugh

* Apply suggestions from code review

Co-authored-by: Natxo Cabré <natxo.cabre@gmail.com>

* missed loglevel env read.

* extend get-state-csv to download both check-product-changes and render-all-categories; output to local-data/

- adds render-all-categories prefix alongside check-product-changes
- saves files to local-data/{prefix}/ (project-root-anchored via __dirname)
- uses path.basename instead of replace to derive local filenames
- anchors dotenv to project root so script works from any cwd

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use CATALOG_BATCH_SIZE=100 for GetUrlKeyQuery batching in mark-up-clean-up

Catalog Service GraphQL rejects queries with >100 SKUs ("Product count exceeds
the maximum allowed (100)"). The batching added in 4625e42 originally used
BATCH_SIZE=50, which was safe, but 22f211d raised BATCH_SIZE to 600 for the
AEM Admin rate limit, inadvertently breaking the catalog query batching.

Fix: add CATALOG_BATCH_SIZE=100 constant, make createBatches accept an optional
size param (defaulting to BATCH_SIZE), and pass CATALOG_BATCH_SIZE explicitly
at the GetUrlKeyQuery call site. The AEM unpublish batches keep BATCH_SIZE=600.

Limit confirmed against live API: 100 SKUs succeed, 101 fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* add comment explaining pLimit reduction from 50 to 20 in enrichProductWithRenderedHash

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Move check-errors and add readme for it

* fix tests

---------

Signed-off-by: Stephen Rugh <rugh@adobe.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Natxo Cabré <natxo.cabre@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants