Skip to content

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-rendererstudioeslimage) and the ECC path documented here (ecc-image-render-serviceecceslimage). 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

  1. 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 either EccSingle or MultiItem.

  2. DTOflow (CQS) → ecclink-projector: CQS notifies ecclink-projector of the link.v2 change. The projector reads the link, inspects the ESL type, and:

  3. If the ESL type is ECC: maps link.v2 fields onto ecclink (resolving the ECC model ID from the ESL type's configuration) and writes the ecclink.v1 DTO at t/{tenantid}/s/{storeid}/links/{linkid}/ecc.
  4. If the ESL type is non-ECC (Studio/segment): ensures any stale ecclink is deleted.
  5. If the link.v2 itself was deleted: deletes the matching ecclink. The by_storeesl alias on ecclink lets ecc-image-render-service observe the deletion.

  6. DTOflow (CQS) → ecc-image-render-service: CQS notifies ecc-image-render-service of the new/updated ecclink. It batch-processes events per tenant+store.

  7. ecc-image-render-service — state assembly (per Ecclink):

  8. Resolve the ecclink (direct event) or look up all ecclink records referencing an updated item (when triggered by a storeitemvalues event via the by_item alias).
  9. Fetch the referenced eccmodel.v1 (Caffeine-cached).
  10. Fetch eccparameters.v1 for the store (Caffeine-cached).
  11. Fetch storeitemvalues.v1 for every item referenced by single-item and multi-item variants.
  12. Load any custom eccfont.v1 fonts referenced by the model (TTF bytes pulled from LFS and registered with AWT).
  13. Map the ESL type to DeviceCapabilities; select the matching ESLView per IPF; run ESLFieldGenerator to produce field data.

  14. 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 single putMany commits all ecceslimage.v1 records to DtoFlow. The ecceslimage.rotation field is set from eccmodel.rotation (NONE or CW_90).

  15. DTOflow (CQS) → eslimage-merger: CQS notifies eslimage-merger of the new ecceslimage. The merger fetches the counterpart studioeslimage for the same (tenant, store, barcode, page):

  16. If both present: merge (Studio output wins for file_path by default; ECC supplies a non-zero rotation if applicable).
  17. If only ECC present and the ESL is non-Studio (per the link variant), fall back to ECC and write eslimage.
  18. If neither present (e.g., deletion of the surviving renderer's output): delete eslimage.

  19. DTOflow (CQS) → pricer-server: CQS notifies pricer-server of the new/updated eslimage. It fetches storeesl (hardware type) and esldriver (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.

  20. Hardware acknowledgment: ESL renders the image and ACKs. pricer-server updates its internal state DB and PUTs storeeslstatus.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 cascadeecc-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
  • Item–ESL Linking — parent flow; link.v2 is written there. The Studio branch is documented in detail.
  • Item Updatestoreitemvalues changes also trigger this pipeline via ecc-image-render-service's by_item alias.
  • ESL Hardware Lifecycle — the storeesl cleanup cascade drives the alias-watch cleanup in ecc-image-render-service.