Skip to content

ecclink-projector

Cloud Run / CQS queue name: ecclink-projector Tech stack: Quarkus (Java), Gradle

ecclink-projector is a narrow projection service. It listens to link.v2 — the canonical, system-agnostic link DTO — and produces ecclink.v1, the ECC-specific representation that ecc-image-render-service needs to render images. The projection is a filter-and-transform step: only links whose ESL type is served by the ECC rendering system are forwarded; links bound for other display systems (e.g., Studio, segment) are dropped.

DTO Ownership

DTO Version Why
ecclink v1 ECC-specific link record; keyed t/{tenantid}/s/{storeid}/links/{linkid}/ecc; carries the ECC model ID, item reference(s), location, and facings in a form directly consumable by ecc-image-render-service

CQS Subscriptions

DTO Version What the service does on change
link v2 Check whether the link references an ECC ESL type; if yes, write or delete the corresponding ecclink.v1; if no (wrong system or barcode removed), delete any existing ecclink.v1 for that barcode

Processing Logic

On link.v2 change:

  1. Read the updated link.v2 record by its DTO ID.
  2. Inspect the ESL type ID carried in the link. The ECC rendering system serves a known set of ESL type IDs (those configured with an ECC model). Links for other display systems are ignored.
  3. If the link targets an ECC ESL type:
  4. Map link.v2 fields to ecclink.v1 structure:
    • esl.barcodesingle.esl.barcode (or multi_item.esl.barcode)
    • esl.esltypeIdsingle.esl.esltypeId
    • item.itemIdsingle.item.itemId
    • item.facingssingle.item.facings
    • locationlocation
    • eccmodelId (resolved from the ESL type's ECC model configuration) → single.eccmodelId
  5. Multi-item links produce a Ecclink.MultiItem variant.
  6. Write the ecclink.v1 record to DtoFlow.
  7. If the link.v2 record was deleted (absent from DtoFlow), delete the corresponding ecclink.v1 record if one exists. The by_storeesl alias on ecclink.v1 is used by ecc-image-render-service to detect the deletion and clean up rendered images.
  8. If the link targets a non-ECC ESL type, ensure no stale ecclink.v1 exists for that barcode and delete if present.

Key design principle: ecclink-projector is stateless between events. It does not cache state; each event is a complete re-evaluation of whether an ecclink should exist for a given barcode.

Service structure

ecclink-projector is the simplest example of a CQS consumer service. Its structure has three parts:

Startup. On boot the service creates its CQS queue if it does not already exist, then immediately enters the poll loop. There is no REST endpoint; the service is entirely event-driven.

Poll loop. The service calls BatchDequeue on the ecclink-projector queue (batch size 100, long-poll wait 60 s). When notifications arrive it reads the changed link.v2 records from the DTOflow Server, runs them through the mapper, writes or deletes the resulting ecclink.v1 records, and acknowledges the batch. If the queue is empty the long-poll blocks until notifications arrive or the timeout elapses, then loops immediately.

Single mapper. A single EcclinkMapper component converts a link.v2 message to an ecclink.v1 message (or signals a delete). There is no branching logic beyond "ECC ESL type or not"; no aggregation, no external calls, no state stored between events.

Integration tests use the DTOflow TestServer Docker image (server + CQS in one container), so tests run against a real DTO store without cloud dependencies.

  • ecc-image-render-service — downstream consumer of ecclink.v1; triggers rendering on every ecclink change
  • dtoflow-migration-helper — during PLT-2484 migration, bridges link.v1link.v2 so ecclink-projector continues to receive events regardless of which version producers write
  • eslimage-merger — indirectly downstream; receives the ecceslimage.v1 produced as a result of ecclink events