Flow: ECC Rendering Pipeline¶
Trigger: A link.v2 ECC variant (EccSingle or MultiItem) is created, updated, or deleted by link-registry
Key services: link-registry, ecclink-projector, ecc-image-render-service, eslimage-merger, pricer-server
Key DTOs: link.v2, ecclink, ecceslimage, eccmodel, eccfont, eccparameters, storeitemvalues, eslimage
The platform has two parallel renderers that both produce per-ESL page images: the Studio path (studio-renderer → studioeslimage) and the ECC path documented here (ecc-image-render-service → ecceslimage). Which path runs is determined by the link.v2 variant: Single and FloatingCanvas route to Studio; EccSingle and MultiItem route to ECC. The two paths run independently and converge at eslimage-merger, which writes the single authoritative eslimage consumed by pricer-server.
This page documents the ECC branch end-to-end. The Studio branch is documented in Item–ESL Linking and Item Update.
Why a separate projector step?¶
link.v2 is system-agnostic — it carries enough information for either Studio or ECC rendering. ecc-image-render-service, however, expects an ECC-shaped record (ecclink) with the ECC model already resolved and only the fields the ECC renderer needs. Rather than burden the renderer with link.v2 traversal and filtering, ecclink-projector does that filtering once: it consumes link.v2 and writes ecclink (or deletes it) for every link whose ESL type is served by ECC. Non-ECC links are dropped silently.
Steps¶
-
link-registry → DTOflow (link.v2): A link with an ECC-bound ESL type is written by
link-registry(during Item–ESL linking or any subsequent update). The link's top-level discriminator is eitherEccSingleorMultiItem. -
DTOflow (CQS) → ecclink-projector: CQS notifies
ecclink-projectorof thelink.v2change. The projector reads the link, inspects the ESL type, and: - If the ESL type is ECC: maps
link.v2fields ontoecclink(resolving the ECC model ID from the ESL type's configuration) and writes theecclink.v1DTO att/{tenantid}/s/{storeid}/links/{linkid}/ecc. - If the ESL type is non-ECC (Studio/segment): ensures any stale
ecclinkis deleted. -
If the
link.v2itself was deleted: deletes the matchingecclink. Theby_storeeslalias onecclinkletsecc-image-render-serviceobserve the deletion. -
DTOflow (CQS) → ecc-image-render-service: CQS notifies
ecc-image-render-serviceof the new/updatedecclink. It batch-processes events per tenant+store. -
ecc-image-render-service — state assembly (per Ecclink):
- Resolve the
ecclink(direct event) or look up allecclinkrecords referencing an updated item (when triggered by astoreitemvaluesevent via theby_itemalias). - Fetch the referenced
eccmodel.v1(Caffeine-cached). - Fetch
eccparameters.v1for the store (Caffeine-cached). - Fetch
storeitemvalues.v1for every item referenced by single-item and multi-item variants. - Load any custom
eccfont.v1fonts referenced by the model (TTF bytes pulled from LFS and registered with AWT). -
Map the ESL type to
DeviceCapabilities; select the matchingESLViewper IPF; runESLFieldGeneratorto produce field data. -
ecc-image-render-service — render and write: Java2D renders the
BufferedImage, encodes to PNG, and writes the bytes to GCS asynchronously. Once all LFS writes for the batch succeed, a singleputManycommits allecceslimage.v1records to DtoFlow. Theecceslimage.rotationfield is set fromeccmodel.rotation(NONEorCW_90). -
DTOflow (CQS) → eslimage-merger: CQS notifies
eslimage-mergerof the newecceslimage. The merger fetches the counterpartstudioeslimagefor the same(tenant, store, barcode, page): - If both present: merge (Studio output wins for
file_pathby default; ECC supplies a non-zerorotationif applicable). - If only ECC present and the ESL is non-Studio (per the link variant), fall back to ECC and write
eslimage. -
If neither present (e.g., deletion of the surviving renderer's output): delete
eslimage. -
DTOflow (CQS) → pricer-server: CQS notifies
pricer-serverof the new/updatedeslimage. It fetchesstoreesl(hardware type) andesldriver(display rotation), reads the PNG bytes from LFS, applies the combined rotation (esldriver.rendering.displayRotation+eslimage.rotation), and transmits over RF/IR to the physical ESL. -
Hardware acknowledgment: ESL renders the image and ACKs.
pricer-serverupdates its internal state DB and PUTsstoreeslstatus.state = OK.
Cleanup via by_storeesl alias watch¶
When an ecclink is deleted — whether because the underlying link.v2 was removed or because the parent storeesl was deleted as part of the terminal-cleanup cascade — ecc-image-render-service cleans up its ecceslimage records for the affected barcode. The mechanic is the platform-level alias-watch cleanup pattern: EIRS subscribes to ecclink.v1 with alias_name = "by_storeesl" and reacts to the barcode-keyed alias-qualified notification with a deleteChildren on the ESL parent. The Studio branch follows the same pattern against studiolink.
Sequence diagram¶
sequenceDiagram
participant LR as link-registry
participant DTOflow
participant ELP as ecclink-projector
participant EIRS as ecc-image-render-service
participant LFS as dtoflow-lfs
participant Merger as eslimage-merger
participant PS as pricer-server
participant ESL as Physical ESL
LR->>DTOflow: Write link.v2 (EccSingle / MultiItem)
DTOflow-->>ELP: CQS: link.v2 changed
ELP->>DTOflow: Read link.v2
Note over ELP: ECC ESL type? Map → ecclink
ELP->>DTOflow: Write ecclink.v1
DTOflow-->>EIRS: CQS: ecclink changed
EIRS->>DTOflow: Fetch eccmodel, eccparameters, storeitemvalues, eccfont
EIRS->>LFS: Upload PNG (Java2D render)
EIRS->>DTOflow: putMany ecceslimage.v1
DTOflow-->>Merger: CQS: ecceslimage changed
Merger->>DTOflow: Fetch studioeslimage (counterpart)
Note over Merger: No Studio output → write ECC eslimage
Merger->>DTOflow: Write eslimage.v1
DTOflow-->>PS: CQS: eslimage changed
PS->>DTOflow: Fetch eslimage, storeesl, esldriver
PS->>LFS: Read PNG bytes
PS->>ESL: Transmit (rotation applied)
ESL-->>PS: Acknowledge
PS->>DTOflow: Write storeeslstatus → OK
Key DTOs¶
| DTO | Role in this flow | Page |
|---|---|---|
link.v2 |
Source link; the EccSingle / MultiItem variant routes through this pipeline |
link.v2 |
ecclink.v1 |
ECC-shaped projection of link.v2; produced by ecclink-projector; consumed by ecc-image-render-service |
ecclink |
eccmodel.v1 |
ECC device-model definition: layout slots, field mappings, rotation; fetched per render | eccmodel |
eccparameters.v1 |
Store-level ECC rendering parameters (singleton per store) | eccparameters |
eccfont.v1 |
TTF font binaries referenced by ECC models | eccfont |
storeitemvalues.v1 |
Live item data evaluated into rendered fields | storeitemvalues |
ecceslimage.v1 |
ECC-rendered PNG record (per ESL page); merger input | ecceslimage |
eslimage.v1 |
Final merged image consumed by pricer-server | eslimage |
storeeslstatus.v1 |
pricer-server lifecycle status; transitions to OK on ACK | storeeslstatus |
Related flows¶
- Item–ESL Linking — parent flow;
link.v2is written there. The Studio branch is documented in detail. - Item Update —
storeitemvalueschanges also trigger this pipeline viaecc-image-render-service'sby_itemalias. - ESL Hardware Lifecycle — the
storeeslcleanup cascade drives the alias-watch cleanup in ecc-image-render-service.