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:
- Read the updated
link.v2record by its DTO ID. - 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.
- If the link targets an ECC ESL type:
- Map
link.v2fields toecclink.v1structure:esl.barcode→single.esl.barcode(ormulti_item.esl.barcode)esl.esltypeId→single.esl.esltypeIditem.itemId→single.item.itemIditem.facings→single.item.facingslocation→locationeccmodelId(resolved from the ESL type's ECC model configuration) →single.eccmodelId
- Multi-item links produce a
Ecclink.MultiItemvariant. - Write the
ecclink.v1record to DtoFlow. - If the
link.v2record was deleted (absent from DtoFlow), delete the correspondingecclink.v1record if one exists. Theby_storeeslalias onecclink.v1is used by ecc-image-render-service to detect the deletion and clean up rendered images. - If the link targets a non-ECC ESL type, ensure no stale
ecclink.v1exists 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.
Related services¶
- ecc-image-render-service — downstream consumer of
ecclink.v1; triggers rendering on every ecclink change - dtoflow-migration-helper — during PLT-2484 migration, bridges
link.v1↔link.v2so ecclink-projector continues to receive events regardless of which version producers write - eslimage-merger — indirectly downstream; receives the
ecceslimage.v1produced as a result of ecclink events