|
| 1 | += Multi-Channel Product Updates Architecture |
| 2 | +:toc: macro |
| 3 | +:toclevels: 2 |
| 4 | +:sectnums: |
| 5 | +:icons: font |
| 6 | +:source-highlighter: rouge |
| 7 | + |
| 8 | +This document outlines a system architecture for managing multi-channel product updates. It ingests vendor data, adjusts pricing with a repricer, and sends updates to marketplaces like Amazon and eBay. |
| 9 | + |
| 10 | +== System Architecture |
| 11 | + |
| 12 | +=== C1 Context Diagram |
| 13 | + |
| 14 | +[source, mermaid] |
| 15 | +---- |
| 16 | +C4Context |
| 17 | +title 🛒 Multi-Channel Product Update System – Context Diagram |
| 18 | +
|
| 19 | +Person(vendor, "🧑 Vendor", "Sends product updates via API, FTP, or email") |
| 20 | +Person(internalOps, "👩💼 Internal Operator", "Monitors and configures pricing rules") |
| 21 | +System(system, "🛍️ Product Update System", "Processes and dispatches product updates to marketplaces") |
| 22 | +System_Ext(marketplace, "🏬 Marketplace Platform", "Receives updates from the internal system") |
| 23 | +
|
| 24 | +Rel(vendor, system, "📤 Sends product & inventory updates") |
| 25 | +Rel(internalOps, system, "⚙️ Manages pricing and monitors system") |
| 26 | +Rel(system, marketplace, "📦 Pushes inventory and pricing updates") |
| 27 | +---- |
| 28 | + |
| 29 | +=== C2 Container Diagram |
| 30 | + |
| 31 | +[source, mermaid] |
| 32 | +---- |
| 33 | +C4Container |
| 34 | +title 🧩 Product Update System – Container Diagram |
| 35 | +
|
| 36 | +Person(vendor, "🧑 Vendor") |
| 37 | +
|
| 38 | +System_Boundary(productUpdateSystem, "🛍️ Product Update System") { |
| 39 | + Container(ingestion, "🔌 Ingestion Service", "Apache Camel / Spring Integration", "Handles API, FTP, and email inputs") |
| 40 | + Container(queue, "📨 Queueing System", "Kafka / RabbitMQ", "Decouples ingestion from processing") |
| 41 | + Container(preprocessor, "🧹 Preprocessing Service", "Spring Boot / Quarkus", "Cleans and normalizes data") |
| 42 | + Container(repricer, "🧮 Repricer Engine", "Drools / Custom Logic", "Applies pricing rules based on cost and business strategy") |
| 43 | + Container(dispatcher, "📤 Marketplace Dispatcher", "Micronaut / Spring WebClient", "Sends updates to marketplaces like Amazon, eBay") |
| 44 | + Container(cache, "⚡ Price Cache", "Redis", "Stores temporary price decisions") |
| 45 | + Container(storage, "💾 Persistent Storage", "PostgreSQL / MinIO", "Stores raw and processed update data") |
| 46 | + Container(monitoring, "📊 Monitoring & Alerting", "Prometheus + Grafana", "Tracks health metrics and errors") |
| 47 | + Container(errorHandler, "❌ Error Handler", "Standalone Service", "Handles retries, dead-letter queues, and logging") |
| 48 | +} |
| 49 | +
|
| 50 | +System_Ext(marketplace, "🏬 Marketplace Platform", "Amazon, eBay, etc.") |
| 51 | +
|
| 52 | +Rel(vendor, ingestion, "📤 Sends product updates") |
| 53 | +Rel(ingestion, queue, "📨 Publishes messages") |
| 54 | +Rel(queue, preprocessor, "🔁 Sends message for cleaning") |
| 55 | +Rel(preprocessor, repricer, "📊 Sends normalized data") |
| 56 | +Rel(repricer, cache, "⚡ Caches price data") |
| 57 | +Rel(repricer, dispatcher, "📤 Sends repriced updates") |
| 58 | +Rel(dispatcher, marketplace, "🚚 Pushes updates") |
| 59 | +Rel(dispatcher, storage, "📝 Logs update results") |
| 60 | +Rel(preprocessor, storage, "🗃️ Stores raw input") |
| 61 | +Rel(dispatcher, errorHandler, "❌ Reports failures") |
| 62 | +Rel(errorHandler, queue, "🔁 Requeues for retry") |
| 63 | +Rel(errorHandler, monitoring, "📢 Triggers alerts") |
| 64 | +---- |
| 65 | + |
| 66 | +=== System Integration Flow |
| 67 | + |
| 68 | +[source, mermaid] |
| 69 | +---- |
| 70 | +graph TD |
| 71 | + subgraph Vendors |
| 72 | + A1[🔌 API Input] --> I[🛠️ Ingestion Layer] |
| 73 | + A2[📂 FTP Listener] --> I |
| 74 | + A3[📧 Email Parser CSV] --> I |
| 75 | + end |
| 76 | +
|
| 77 | + I --> Q[📨 Kafka / RabbitMQ Queue] |
| 78 | +
|
| 79 | + Q --> P[🧹 Preprocessing Service] |
| 80 | + P --> S1[(💾 Raw Data Storage - MinIO)] |
| 81 | + P --> V[🧪 Validation & Normalization] |
| 82 | + V --> R[🧮 Repricer Service] |
| 83 | + R --> S2[(⚡ Price Cache - Redis)] |
| 84 | + R --> D[(📦 Final Update Queue)] |
| 85 | +
|
| 86 | + D --> M1[🛒 Amazon Sync Service] |
| 87 | + D --> M2[🛍️ eBay Sync Service] |
| 88 | + D --> M3[🏬 Other Channels] |
| 89 | +
|
| 90 | + M1 --> O1[(🔁 API Response)] |
| 91 | + M2 --> O2 |
| 92 | + M3 --> O3 |
| 93 | +
|
| 94 | + subgraph Monitoring & Reliability |
| 95 | + E1[❌ Error Queue] |
| 96 | + E2[🔁 DLQ / Retry Logic] |
| 97 | + E3[📊 Alerting Prometheus + Grafana] |
| 98 | + end |
| 99 | +
|
| 100 | + M1 -->|❗ Failure| E1 |
| 101 | + M2 -->|❗ Failure| E1 |
| 102 | + E1 --> E2 |
| 103 | + E2 --> Q |
| 104 | + E2 --> E3 |
| 105 | +---- |
| 106 | + |
| 107 | + |
| 108 | +== Data Flow Breakdown |
| 109 | + |
| 110 | +[source, mermaid] |
| 111 | +---- |
| 112 | +graph LR |
| 113 | + subgraph Ingestion |
| 114 | + A1[🔌 API Input] |
| 115 | + A2[📂 FTP Listener] |
| 116 | + A3[📧 Email Parser CSV] |
| 117 | + A1 --> I[🛠️ Ingestion Service] |
| 118 | + A2 --> I |
| 119 | + A3 --> I |
| 120 | + end |
| 121 | +
|
| 122 | + I --> Q[📨 Kafka / RabbitMQ Queue] |
| 123 | +
|
| 124 | + subgraph Processing |
| 125 | + Q --> P[🧹 Preprocessor] |
| 126 | + P --> N[🧪 Normalization] |
| 127 | + N --> S1[(💾 Raw Data Backup - MinIO)] |
| 128 | + end |
| 129 | +
|
| 130 | + N --> R[🧮 Repricer Engine] |
| 131 | + R --> C[⚡ Redis Price Cache] |
| 132 | +
|
| 133 | + subgraph Dispatch |
| 134 | + R --> UQ[📦 Final Update Queue] |
| 135 | + UQ --> D1[🛒 Amazon Worker] |
| 136 | + UQ --> D2[🛍️ eBay Worker] |
| 137 | + UQ --> D3[🏬 Other Marketplace Worker] |
| 138 | + end |
| 139 | +
|
| 140 | + D1 --> A1Resp[(🔁 Amazon API Resp)] |
| 141 | + D2 --> A2Resp[(🔁 eBay API Resp)] |
| 142 | + D3 --> A3Resp[(🔁 Other Resp)] |
| 143 | +
|
| 144 | + subgraph Failure Handling |
| 145 | + D1 -->|❗ Fail| E1[❌ Error Queue] |
| 146 | + D2 -->|❗ Fail| E1 |
| 147 | + D3 -->|❗ Fail| E1 |
| 148 | + E1 --> E2[🔁 DLQ & Retry Service] |
| 149 | + E2 --> Q |
| 150 | + end |
| 151 | +
|
| 152 | + subgraph Monitoring & Observability |
| 153 | + I --> M[📊 Metrics Prometheus] |
| 154 | + P --> M |
| 155 | + R --> M |
| 156 | + D1 --> M |
| 157 | + E1 --> M |
| 158 | + E2 --> M |
| 159 | + end |
| 160 | +---- |
| 161 | + |
| 162 | +=== 1. Vendor Ingestion Layer |
| 163 | + |
| 164 | +- **API**: REST endpoints for structured input |
| 165 | +- **FTP Listener**: Scheduled job polling vendor files |
| 166 | +- **Email Parser**: Extracts CSV from email attachments |
| 167 | +- Normalized into a unified schema and sent to Kafka or RabbitMQ for decoupling and backpressure. |
| 168 | + |
| 169 | +=== 2. Processing & Repricing |
| 170 | + |
| 171 | +- **Preprocessing**: Cleans and validates incoming payloads. |
| 172 | +- **Raw Storage**: S3-compatible store (e.g., MinIO) for auditing and reprocessing. |
| 173 | +- **Repricer**: Applies pricing strategies using input cost, competition, and business rules. |
| 174 | +- **Cache**: Redis for fast access to recent pricing decisions. |
| 175 | + |
| 176 | +=== 3. Update Dispatch |
| 177 | + |
| 178 | +- **Dispatch Queue**: Stores final update payloads. |
| 179 | +- **Channel Workers**: One per marketplace (Amazon, eBay, etc.), using async non-blocking HTTP clients like `WebClient` or `Apache HttpAsyncClient`. |
| 180 | +- **Rate Limiting**: Use of a `resilience4j`-based circuit breaker or retry policy. |
| 181 | + |
| 182 | +=== 4. Error Handling & Observability |
| 183 | + |
| 184 | +- **Error Queue**: Captures failures to isolate processing. |
| 185 | +- **DLQ / Retry Logic**: Attempts reprocessing with exponential backoff. |
| 186 | +- **Prometheus + Grafana**: Metric scraping and dashboards. |
| 187 | +- **Structured Logs**: Output JSON logs via OpenTelemetry or Logstash-compatible format. |
| 188 | + |
| 189 | +== ☁️ Scalability Considerations |
| 190 | + |
| 191 | +- Kafka/RabbitMQ enable **horizontal scaling** of workers. |
| 192 | +- Stateless microservices (e.g., using Spring Boot or Quarkus) can be **scaled independently**. |
| 193 | +- Redis + S3 provide separation between fast lookup and deep storage. |
| 194 | + |
| 195 | +== 🔧 Technology Stack (Open Source) |
| 196 | + |
| 197 | +- **Ingestion**: Apache Camel / Spring Integration |
| 198 | +- **Queueing**: Apache Kafka or RabbitMQ |
| 199 | +- **Processing**: Quarkus / Micronaut / Spring Boot |
| 200 | +- **Storage**: PostgreSQL for metadata, MinIO for object store |
| 201 | +- **Repricing**: Business Rule Engine (Drools or custom) |
| 202 | +- **Cache**: Redis |
| 203 | +- **Observability**: Prometheus, Grafana, Loki |
| 204 | +- **Orchestration**: Kubernetes (K8s) |
| 205 | +- **Retry / Circuit Breaker**: Resilience4j |
| 206 | + |
| 207 | +== 🛠 Design Choices |
| 208 | + |
| 209 | +- *Event-driven architecture*: Enables decoupling and asynchronous processing. |
| 210 | +- *Polyglot persistence*: Combines cache, object store, and relational DBs for performance and flexibility. |
| 211 | +- *Replayability*: Kafka topics and raw data storage allow easy replay on failure. |
| 212 | +- *Cloud-native ready*: Designed for containerized environments with horizontal scalability. |
| 213 | + |
| 214 | +== ⚖️ Trade-offs and Design Decisions |
| 215 | + |
| 216 | +- **Open-source vs. managed services**: |
| 217 | +Chose open-source tools (Kafka, Redis, MinIO) for neutrality and control. |
| 218 | +→ Trade-off: full responsibility for scaling and ops. |
| 219 | + |
| 220 | +- **State in cache/queue vs. database**: |
| 221 | +Handled transient state (e.g., repricing, retries) via Redis and Kafka for throughput and decoupling. |
| 222 | +→ Trade-off: more distributed coordination, eventual consistency. |
| 223 | + |
| 224 | +- **Rule-based vs. static repricing**: |
| 225 | +Enabled Drools and custom logic for flexible pricing strategies. |
| 226 | +→ Trade-off: higher complexity and need for business rule governance. |
| 227 | + |
| 228 | +- **Internal scalability vs. API constraints**: |
| 229 | +System scales horizontally, but marketplaces impose rate limits. |
| 230 | +→ Trade-off: real-world throughput is gated by external dependencies. |
0 commit comments