Skip to content

studio-renderer

Cloud Run / CQS queue name: studio-renderer Legacy name: image-render-service (deprecated) Tech stack: Node.js (see .nvmrc for pinned version), Express, Fabric.js, express-openapi-validator

studio-renderer is the image generation service for the studio rendering path. It listens to change notifications across six DTO types and, for any ESL whose rendering inputs have changed, fetches the current state of all required data, uses Fabric.js to render the SVG design with live item property values substituted, produces a PNG at the correct resolution for the target ESL device type, uploads the binary to DTOflow LFS, and writes a studioeslimage.v1 DTO pointing at the LFS path. During the current migration period it also writes the legacy renderedimage.v1 DTO via dtoflow-migration-helper so that PricerServer consumers that have not yet migrated to studioeslimage continue to receive images.

DTO Ownership

DTO Version Why this service owns it
studioeslimage v1 The rendered PNG image for a specific ESL on the studio path. Carries the LFS file_path, rotation, and source link metadata. This is the canonical post-migration image output.
renderedimage v1 (legacy) Pre-migration image DTO still consumed by legacy PricerServer code paths. Written via dtoflow-migration-helper during the migration window; will be retired once all consumers are on studioeslimage/eslimage.

CQS Subscriptions

DTO Version What the service does when it receives a change
studiolink v1 Primary trigger. A new or updated studiolink means the resolved design for an ESL has changed. The service fetches the full render inputs and triggers a full re-render. A deleted studiolink causes the service to delete the corresponding studioeslimage.
storeitemvalues v1 Item property values have changed. The service looks up which ESLs are linked to the affected items (via the active studiolink for each ESL) and re-renders those whose displayed values differ.
design v1 A design has been republished (content or property mappings changed). The service re-renders all ESLs currently displaying this design.
storeesl v1 An ESL assignment has changed (new ESL added to store, or ESL removed). On addition, if a studiolink already exists, an initial render is triggered. On deletion, the service deletes the associated studioeslimage.
canvasdesign v1 A canvas design (multi-page container) has changed. Any ESL displaying a page of this canvas design is re-rendered.
designerlink v1 A pre-evaluation link reference has changed. Used to resolve legacy single-design ESLs that bypass the scenario evaluation path.

Processing Logic

Render pipeline for a single ESL:

  1. Trigger received — one of the six subscribed DTO types changes for an ESL barcode.
  2. State assembly — the service fetches from DTOflow: the current studiolink.v1 (resolved design ID + item context), the design.v1 content (SVG template + property-mapping rules), the storeitemvalues.v1 for the linked item, and the storeesl.v1 for screen-size and colour-depth information.
  3. SVG template rendering — Fabric.js parses the SVG template. Each property-mapping rule in the design is applied: text elements are replaced with the corresponding item property value, barcode elements are generated from item ID fields, image placeholders are resolved from designimage LFS paths.
  4. PNG export — The canvas is exported to a PNG buffer at the pixel dimensions specified by the esltype associated with the ESL. Page rotation from storeeslstatus or storeesl is applied.
  5. LFS upload — The PNG buffer is uploaded to DTOflow LFS. The returned LFS path is stable for identical content (content-addressed).
  6. DTO write — A studioeslimage.v1 DTO is written to DTOflow with the LFS path, rotation, and metadata. During migration, dtoflow-migration-helper additionally writes a renderedimage.v1 at the same LFS path.

Delete path: When a studiolink is deleted (ESL unlinked from all designs), the renderer deletes the studioeslimage DTO, which signals downstream services (e.g. eslimage-merger) that no studio image exists for this ESL.

Heavy fan-out via re-enqueue: A design.v1 or canvasdesign.v1 change can imply re-rendering every ESL in a multi-store tenant. Rather than render all of them under one ack lease, the renderer hands the notification back to CQS via ReEnqueue, splitting it first into per-store parent_id notifications and then, on dequeueing each per-store notification, into per-ESL dto_id notifications. Urgent single-ESL renders interleave naturally between the pieces of the original job.

Cleanup via alias watch (by_storeesl): studio-renderer subscribes to studiolink.v1 with alias_name = "by_storeesl" to receive a barcode-keyed deletion trigger; on NOT_FOUND it deletes the orphaned studioeslimage records for that ESL. This is an instance of the platform-level alias-watch cleanup pattern; see the ESL lifecycle cleanup cascade for the upstream trigger.

Preview endpoint: The service exposes a synchronous REST endpoint (POST /api/image-rendering/v1/preview) that accepts an inline design payload and item data and returns a rendered PNG without writing any DTOs. Used by the Studio UI for live design previews.

Integration tests: Run inside Docker to eliminate platform-specific font rendering differences. The test suite uses zero tolerance for pixel diff, enforced by a custom Jest environment.

Memory management: Fabric.js Canvas objects are explicitly disposed after each render to prevent heap growth. The service includes K6 load test scripts (npm run k6:load, npm run k6:stress, npm run k6:soak) and supports heap-snapshot profiling via npm run profile-memory to detect Fabric.js or Canvas object leaks.

Monitoring: Alert policies and dashboards are managed in platform-gcp-resources.

  • studio-link-evaluator — produces the studiolink.v1 DTOs that are the primary render trigger
  • studio-design-library — produces design.v1, canvasdesign.v1, designerlink.v1 that the renderer subscribes to
  • link-registry — produces storeesl.v1 consumed here for ESL device metadata
  • dtoflow-migration-helper — bridges studioeslimage.v1 output to legacy renderedimage.v1 consumers
  • eslimage-merger — subscribes to studioeslimage.v1 and merges with ECC images to produce the final eslimage