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:
- Trigger received — one of the six subscribed DTO types changes for an ESL barcode.
- State assembly — the service fetches from DTOflow: the current
studiolink.v1(resolved design ID + item context), thedesign.v1content (SVG template + property-mapping rules), thestoreitemvalues.v1for the linked item, and thestoreesl.v1for screen-size and colour-depth information. - 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
designimageLFS paths. - PNG export — The canvas is exported to a PNG buffer at the pixel dimensions specified by the
esltypeassociated with the ESL. Page rotation fromstoreeslstatusorstoreeslis applied. - LFS upload — The PNG buffer is uploaded to DTOflow LFS. The returned LFS path is stable for identical content (content-addressed).
- DTO write — A
studioeslimage.v1DTO is written to DTOflow with the LFS path, rotation, and metadata. During migration,dtoflow-migration-helperadditionally writes arenderedimage.v1at 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.
Related services¶
- studio-link-evaluator — produces the
studiolink.v1DTOs that are the primary render trigger - studio-design-library — produces
design.v1,canvasdesign.v1,designerlink.v1that the renderer subscribes to - link-registry — produces
storeesl.v1consumed here for ESL device metadata dtoflow-migration-helper— bridgesstudioeslimage.v1output to legacyrenderedimage.v1consumerseslimage-merger— subscribes tostudioeslimage.v1and merges with ECC images to produce the finaleslimage