Stock Import - Overview¶
Purpose¶
The Stock Import island is a separate Symfony application that handles importing stock data from 50-60 suppliers. It runs on an isolated infrastructure for security reasons (FTP server receiving external files).
Architecture¶
┌─────────────────────────────────────────────┐
│ STOCK IMPORT │
│ │
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ FTP Watcher │───►│ File Processor │ │
│ │ (cron) │ │ │ │
│ └─────────────┘ └────────┬─────────┘ │
│ │ │
│ ┌────────▼─────────┐ │
│ │ Article Matching │ │
│ │ Engine │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌────────▼─────────┐ │
│ │ Stock Update │ │
│ │ Service │ │
│ └────────┬─────────┘ │
│ │ │
└──────────────────────────────┼──────────────┘
│ REST API
▼
┌─────────────────────┐
│ WEBSHOP │
└─────────────────────┘
Components¶
1. FTP Watcher¶
- Monitors FTP directory for new files
- Runs as scheduled cron job
- Moves processed files to archive
2. File Processor¶
- Parses CSV/XML files
- Supplier-specific format handling
- Validates file structure
3. Article Matching Engine¶
- Matches supplier articles to internal catalog
- Confidence scoring for uncertain matches
- Manual review queue for low-confidence matches
4. Stock Update Service¶
- Updates stock levels in database
- Pushes updates to Webshop via API
Security¶
- FTP server is isolated from main network
- Only receives files, no outbound connections
- Stock Import pulls files, no push access
Data Flow¶
- Supplier uploads CSV/XML to FTP
- FTP Watcher detects new file
- File Processor parses based on supplier config
- Matching Engine maps to internal articles
- Stock Update sends to Webshop API
- File moved to archive with processing log
Key Improvements¶
| Current | New |
|---|---|
| Matching sometimes incorrect | Confidence scoring + review queue |
| No audit trail | Full matching history |
| Manual investigation | Alerting for problems |
| Single matching attempt | Multi-identifier verification |
Connector Runtime Contract (AR-004 Closure)¶
All supplier connectors (FTP/API/CSV/XML) run through one reliability contract.
Idempotency¶
Each supplier feed message must carry a deterministic idempotency key:
supplier-feed:{supplierId}:{sourceType}:{externalFileNameOrCursor}:{contentHash}
Rules:
- Duplicate key means acknowledge and skip side effects.
- Key is stored in consumer inbox/dedup table.
- Stock write operations must be upsert/idempotent per
(supplierId, articleNumber, batchId).
Retry and Backoff¶
- Temporary failures (
5xx, connection timeout, transient auth errors) retry with exponential backoff. - Validation failures (
4xxmalformed payload, schema mismatch) do not blind retry; they are marked failed with operator action required. - Max retry attempts are connector-configurable with safe defaults.
Dead-Letter Queue and Replay¶
- Exhausted retries move message to supplier DLQ.
- DLQ records retain payload pointer, error stack, supplier id, and idempotency key.
- Replay command must support scoped replay by supplier and date range.
Checkpoints and Watermarks¶
Keep resumable state per supplier connector:
last_successful_fileorcursorlast_successful_timestamplast_processed_hashlast_batch_id
Restart behavior:
- Resume from last committed checkpoint.
- Re-read overlap window where needed; idempotency keys prevent duplicates.
Queue Model¶
Queue classes:
high-priority: incremental stock updates and urgent correction batches.bulk: full feed imports and backfills.
Minimum Operational Metrics¶
- Import success rate by supplier.
- Retry count and DLQ depth by supplier.
- Processing lag from file arrival to committed stock update.
- Duplicate-delivery drop count.
Acceptance Scenarios (Gherkin)¶
Feature: Supplier connector runtime reliability
Scenario: Duplicate supplier feed is ignored safely
Given supplier feed message M with idempotency key K was already processed
When message M is delivered again
Then no duplicate stock mutation should be committed
And the message should be acknowledged as duplicate
Scenario: Temporary connector failure is retried and succeeds
Given supplier connector receives a temporary upstream timeout
When retry policy is applied
Then the message should be retried with backoff
And successful processing should commit stock and advance checkpoint
Scenario: Exhausted retries route to DLQ and can be replayed
Given supplier feed processing keeps failing with temporary errors
When max retries are exhausted
Then the message should be moved to supplier DLQ
When operator replays the message after fix
Then processing should succeed without duplicate side effects