Skip to content

Flow: Item–ESL Linking

Trigger: Store worker scans an ESL barcode and associates it with a retail item in the Plaza Mobile app Key services: link-registry, studio-link-evaluator, studio-renderer, eslimage-merger, pricer-server Key DTOs: storeesl, link.v2, studiolink, storeitemvalues, studioeslimage, ecceslimage, eslimage

This is the core end-to-end pipeline of the system. When a store worker physically walks the store with the Plaza Mobile app and scans an ESL barcode then selects an item, the entire chain from association to pixel-on-glass is set in motion. link-registry records the pairing, studio-link-evaluator resolves which design should be shown (evaluating CEL rules against live item data and any configured scenario overrides), studio-renderer produces a rendered PNG, eslimage-merger selects the authoritative image from potentially multiple renderer outputs, and pricer-server (the on-premise gateway) consumes the final eslimage directly from CQS and transmits it to the physical ESL over the in-store RF/IR network. The flow is fully reactive: each service subscribes to CQS notifications for the DTOs it depends on, so there is no orchestrator and no polling. Idempotency is achieved because every service writes its output DTO only when the computed result actually differs from the current stored state — a duplicate notification does not re-trigger downstream work.

Steps

  1. Store worker → Plaza Mobile app: The store worker opens Plaza Mobile, points the camera at an ESL, and scans its barcode. They then search for or scan the product they want to associate with that ESL and confirm the pairing.

  2. Plaza Mobile → link-registry: Plaza Mobile calls the link-registry API with the ESL barcode and item identifier. link-registry validates both identifiers, resolves the store context (tenant ID, store ID), and determines the applicable rendering system (Studio or ECC) based on tenant configuration.

  3. link-registry → DTOflow (storeesl + link.v2): link-registry writes two DTOs atomically. First it creates or updates the storeesl DTO (id: t/{tenantid}/s/{storeid}/esls/{barcode}) recording the ESL hardware type, department, and tenant/store scope. Second it writes the link.v2 DTO (id: t/{tenantid}/s/{storeid}/links/{linkid}) with the Studio Single variant containing the item reference and an optional forced_design_id. The by_storeesl alias on link.v2 (at t/{tenantid}/s/{storeid}/esls/{barcode}/link) enables per-barcode subscriptions.

  4. DTOflow (CQS) → studio-link-evaluator: CQS emits a change notification on link.v2. studio-link-evaluator subscribes to link.v2 changes. It fetches the updated link.v2, the relevant communicationpack (containing scenario override rules expressed in CEL), and the current storeitemvalues for the linked item. It evaluates the CEL expression to determine the winning design: if forced_design_id is set that design wins unconditionally; otherwise the scenario rules may select a design based on item attributes (e.g. promotional flag → promotional design).

  5. studio-link-evaluator → DTOflow (studiolink): studio-link-evaluator writes a studiolink DTO (id suffix /studio) capturing the resolved forced_design_id, item reference, barcode, and render context. The by_storeesl, by_item, by_design, and by_canvasdesign aliases enable downstream services to subscribe efficiently. If the evaluation result is identical to the current studiolink, no write is performed and the pipeline stops here.

  6. DTOflow (CQS) → studio-renderer: CQS emits a change notification on studiolink. studio-renderer fetches the studiolink, the resolved design DTO, and the storeitemvalues for the item. It instantiates every bound property field with the item's live data.

  7. studio-renderer → dtoflow-lfs + DTOflow (studioeslimage): studio-renderer renders the design layout with live item data into a PNG at the ESL's native resolution and rotation. It uploads the PNG to dtoflow-lfs (receiving a file_path) and writes a studioeslimage DTO (id path t/{tenantid}/s/{storeid}/esls/{barcode}/pages/{pagenum}/studioimage). If an ECC renderer also has output for this ESL (ecceslimage), both images coexist briefly until the merger resolves them.

  8. DTOflow (CQS) → eslimage-merger: CQS notifies eslimage-merger of the new studioeslimage. The merger fetches both studioeslimage and ecceslimage (if any) for this barcode+page. Merge priority: Studio output wins if present; ECC output is used as fallback; if neither exists the eslimage DTO is deleted. The merger writes the eslimage DTO (id suffix /image) pointing to the winning file_path and recording the source kind (studio or ecc).

  9. DTOflow (CQS) → pricer-server: CQS notifies pricer-server of the new or updated eslimage. pricer-server fetches the eslimage to get the file_path and rotation, fetches the storeesl DTO to resolve the ESL's hardware type, and reads the esldriver to determine display rotation.

  10. pricer-server → ESL hardware: pricer-server downloads the PNG from dtoflow-lfs, applies the combined rotation (esldriver.rendering.displayRotation + eslimage.rotation), and pushes it over the in-store RF/IR network to the physical ESL. The ESL renders the image on its e-ink display and acknowledges receipt. pricer-server records the acknowledgment in its internal state DB and PUTs storeeslstatus with state OK.

Sequence diagram

sequenceDiagram
    participant W as Store Worker
    participant App as Plaza Mobile
    participant LR as link-registry
    participant DTOflow
    participant SLE as studio-link-evaluator
    participant SR as studio-renderer
    participant Merger as eslimage-merger
    participant PS as pricer-server
    participant ESL as Physical ESL

    W->>App: Scan ESL barcode + select item
    App->>LR: Link ESL barcode to item
    LR->>DTOflow: Write storeesl DTO
    LR->>DTOflow: Write link.v2 DTO (Studio/Single)
    DTOflow-->>SLE: CQS: link.v2 changed
    SLE->>DTOflow: Fetch link.v2, communicationpack, storeitemvalues
    Note over SLE: Evaluate CEL → resolve winning design
    SLE->>DTOflow: Write studiolink DTO
    DTOflow-->>SR: CQS: studiolink changed
    SR->>DTOflow: Fetch studiolink, design, storeitemvalues
    SR->>DTOflow: Upload PNG → dtoflow-lfs
    SR->>DTOflow: Write studioeslimage DTO
    DTOflow-->>Merger: CQS: studioeslimage changed
    Merger->>DTOflow: Fetch studioeslimage + ecceslimage (if any)
    Note over Merger: Studio wins; write merged result
    Merger->>DTOflow: Write eslimage DTO
    DTOflow-->>PS: CQS: eslimage changed
    PS->>DTOflow: Fetch eslimage, storeesl, esldriver
    PS->>ESL: Push PNG over RF/IR (rotation applied)
    ESL-->>PS: Acknowledge image received
    PS->>DTOflow: Write storeeslstatus → OK

Key DTOs involved

DTO Role in this flow Page
storeesl.v1 ESL identity record; binds barcode to hardware type and store; consumed by pricer-server for hardware routing storeesl.v1
link.v2 Primary association between item and ESL; top-level Studio/ECC split; drives the whole pipeline link.v2
communicationpack.v1 Contains tenant-level CEL scenario rules that studio-link-evaluator uses to select the winning design communicationpack.v1
storeitemvalues.v1 Live key-value item data (price, name, flags) fetched during evaluation and rendering storeitemvalues.v1
studiolink.v1 Evaluated render instruction: resolved design + item + barcode; triggers studio-renderer studiolink.v1
design.v1 Published immutable label layout fetched by studio-renderer design.v1
studioeslimage.v1 Studio renderer output (PNG path + rotation); input to eslimage-merger studioeslimage.v1
ecceslimage.v1 ECC renderer output (PNG path + rotation); fallback input to eslimage-merger ecceslimage.v1
eslimage.v1 Merged authoritative page image; consumed by pricer-server eslimage.v1
storeeslstatus.v1 pricer-server-owned lifecycle status; transitions to OK on successful image acknowledgment storeeslstatus.v1
  • Design Publication — a design change triggers re-evaluation starting at step 4 of this flow
  • Item Update — an item data change triggers re-evaluation starting at step 4 of this flow, with an early-exit if evaluation is unchanged
  • ESL Hardware Lifecycle — the storeesl DTO created in step 3 is the anchor for the ESL's entire hardware lifecycle