19 KiB
Apache Flink ECS Test Case - Architecture
System Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ HTTP Request (Trigger) │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ API Gateway (HTTP) │ │
│ │ /trigger endpoint │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Trigger Lambda │ │
│ │ (Ingestion Handler) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────────┼───────────────┬──────────────┐ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ ┌─────────┐ │
│ │ External API │ │ S3 Landing │ │ S3 Audit │ │ ECS │ │
│ │ (Mock) │ │ Bucket │ │ Object │ │ RunTask │ │
│ │ │ │ │ │ │ │ API │ │
│ │ GET /data │ │ ingested/ │ │ audit/ │ │ │ │
│ └──────┬───────┘ │ data.json │ │ {id}.json │ └────┬────┘ │
│ │ └───────┬───────┘ └──────────────┘ │ │
│ │ │ │ │
│ │ │ ┌─ S3 Metadata ────────────┐ │ │
│ │ │ │ - correlation_id │ │ │
│ └─────────────────►│ │ - audit_key (link) │ │ │
│ API Response │ │ - schema_version │ │ │
│ (JSON) │ │ - source: trigger_lambda │ │ │
│ │ └───────────────────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌───────────────────────┐◄───────────────────┘ │
│ │ ECS Fargate Task │ │
│ │ (PyFlink Batch Job) │ │
│ │ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ PyFlink Job │ │ │
│ │ │ (main.py) │ │ │
│ │ │ │ │ │
│ │ │ 1. Read S3 │ │ │
│ │ │ 2. Validate │ │ │
│ │ │ 3. Transform │ │ │
│ │ │ 4. Write S3 │ │ │
│ │ └────────┬────────┘ │ │
│ └───────────┼──────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ S3 Processed Bucket │ │
│ │ processed/data.json │ │
│ │ │ │
│ │ + S3 Metadata: │ │
│ │ - correlation_id │ │
│ │ - source_key (link)│ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ CloudWatch Logs │ │
│ │ /ecs/tracer-flink │ │
│ │ │ │
│ │ - Job execution │ │
│ │ - Validation logs │ │
│ │ - Error traces │ │
│ │ - Audit events │ │
│ └───────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Component Breakdown
1. Trigger Lambda (trigger_lambda/handler.py)
Purpose: Ingestion orchestrator + ECS task launcher Responsibilities:
- Receives HTTP POST requests via API Gateway
- Fetches data from Mock External Vendor API
- Writes audit payload to S3 (request/response tracking)
- Writes ingested data to S3 Landing Bucket with metadata
- Starts ECS Flink task via RunTask API
- Returns correlation_id and task ARN
Environment Variables:
LANDING_BUCKET: S3 bucket for raw dataPROCESSED_BUCKET: S3 bucket for transformed dataEXTERNAL_API_URL: Mock external API endpointECS_CLUSTER: Flink ECS cluster ARNTASK_DEFINITION: Flink task definition ARNSUBNET_IDS: VPC subnet IDs for Fargate tasksSECURITY_GROUP_ID: Security group for Fargate tasks
2. Mock External Vendor API (mock_api_lambda)
Purpose: Simulates upstream data source
Location: Shared from tests/shared/external_vendor_api/handler.py
Capabilities:
GET /data: Returns JSON dataPOST /config: Configure schema changes (for testing failures)GET /health: Health check endpointGET /config: Get current configuration- Can inject schema changes to trigger validation errors
3. S3 Landing Bucket
Purpose: Raw data storage Contents:
ingested/{timestamp}/data.json: Raw API responsesaudit/{correlation_id}.json: Full request/response audit trail
Metadata (attached to objects):
correlation_id: Unique identifier for trackingaudit_key: Reference to audit payloadschema_version: Data schema versionsource: Ingestion source identifier
4. ECS Fargate Task (PyFlink)
Purpose: Batch data processing Components:
- PyFlink Runtime: Python batch job with domain validation
- Batch Job: One-shot execution (runs and exits)
- Container:
python:3.11-slimwith boto3
Execution Model:
- Triggered on-demand via ECS RunTask API
- Reads input from S3 landing bucket
- Validates schema, transforms data
- Writes output to S3 processed bucket
- Exits with status code (0 = success, non-zero = failure)
5. PyFlink Job (pipeline_code/flink_job/main.py)
Name: tracer_flink_ml_feature_pipeline
Purpose: Feature engineering for ML model consumption
Steps:
-
Read Event Data
- Reads JSON from S3 landing bucket
- Extracts correlation_id from S3 metadata
- Returns raw event payload
-
Validate & Engineer Features
- Validates required fields (
event_id,user_id,event_type,timestamp) - Computes ML features from raw_features:
- Normalized numerical features
- One-hot encoded categorical features
- Interaction features (value_per_second, avg_value_per_count)
- Temporal features (is_weekend, hour_of_day)
- Generates feature hash for versioning
- Raises
DomainErroron validation failure
- Validates required fields (
-
Write Feature-Engineered Output
- Writes processed features to S3 processed bucket
- Includes feature hash for ML model versioning
- Adds metadata linking back to source event
- Preserves correlation_id for tracing
Error Handling:
- Catches
DomainErrorand logs structured error - Includes correlation_id in all logs
- Exits with non-zero status on failure
6. S3 Processed Bucket
Purpose: Transformed data storage Contents:
processed/{correlation_id}/data.json: Validated and transformed records
Metadata:
correlation_id: Trace back to ingestionsource_key: Original S3 object key
7. CloudWatch Logs
Log Group: /ecs/tracer-flink
Content:
- Flink job startup logs
- Data processing logs
- Validation errors with correlation_id
- Stack traces on failure
Data Flow (Happy Path)
1. HTTP POST /trigger
└─> API Gateway
└─> Trigger Lambda
├─> GET Mock External API /data
│ └─> Returns: ML events with raw_features
│
├─> PUT S3 audit/{id}.json (API request/response)
│
├─> PUT S3 ingested/{timestamp}/data.json
│ └─> Metadata: correlation_id, audit_key, schema_version
│
└─> ECS RunTask (Flink ML job)
└─> Container starts with env vars:
- LANDING_BUCKET
- PROCESSED_BUCKET
- CORRELATION_ID
- S3_KEY
2. ECS Flink Task (ML Feature Engineering)
└─> Executes: python main.py
├─> Read S3 ingested/{timestamp}/data.json
│
├─> Validate event schema (event_id, user_id, event_type, timestamp)
│
├─> Engineer ML features from raw_features:
│ * Normalized values
│ * One-hot encoded event types
│ * Interaction features
│ * Temporal features
│
├─> Compute feature hash for versioning
│
└─> PUT S3 processed/{correlation_id}/data.json
└─> Metadata: correlation_id, source_key, feature_hash
3. CloudWatch Logs
└─> All job execution logs captured in /ecs/tracer-flink
Data Flow (Failure Path - Schema Mismatch)
1. HTTP POST /trigger?inject_error=true
└─> API Gateway
└─> Trigger Lambda
├─> POST Mock External API /config {"inject_schema_change": true}
│
├─> GET Mock External API /data
│ └─> Returns: ML events without event_id ❌ Missing event_id
│
├─> PUT S3 audit/{id}.json (captures schema change)
│
├─> PUT S3 ingested/{timestamp}/data.json
│ └─> Metadata: schema_change_injected=True
│
└─> ECS RunTask (Flink ML job)
2. ECS Flink Task (ML Feature Engineering)
└─> Executes: python main.py
├─> Read S3 ingested/{timestamp}/data.json ✓
│
├─> Validate event schema ❌ FAILS
│ └─> DomainError: Missing required field 'event_id'
│ (Critical for ML feature deduplication)
│
└─> Task exits with status code 1
3. CloudWatch Logs
└─> Error trace includes:
├─> [FLINK][ERROR] Schema validation failed: Missing fields ['event_id']
├─> correlation_id for tracing
├─> S3 input location
└─> Stack trace
Investigation Path (What Agent Should Detect)
When investigating a pipeline failure, the Tracer Agent should:
1. Start: ECS Task Logs (CloudWatch)
- Retrieve job execution logs from
/ecs/tracer-flink - Identify failed validation step
- Extract error:
Missing required field 'customer_id' - Extract
correlation_idfrom logs
2. Input Data Store (S3 Landing)
- Get S3 object path from logs:
s3://landing-bucket/ingested/{timestamp}/data.json - Inspect object content and metadata
- Detect schema version mismatch
- Find
audit_keyin metadata
3. Schema Validation
- Compare actual fields vs. required fields
- Identify missing field:
event_id - Confirm schema mismatch cause (breaks ML feature deduplication)
4. Data Lineage (S3 Metadata)
- Read
correlation_idfrom object metadata - Read
audit_keyreference - Trace origin to Trigger Lambda
5. Upstream Compute (Trigger Lambda)
- Retrieve Lambda code and configuration
- Get recent invocations using
correlation_id - Identify external API call in logs
6. External Dependency (Audit Payload) 🎯 GOAL
- Retrieve audit object:
s3://landing-bucket/audit/{correlation_id}.json - Inspect full request/response from external API
- Confirm external API returned data without
customer_id - Identify schema version change:
v1.0→v2.0
Root Cause
External event stream API changed schema from v1.0 to v2.0, removing event_id field (critical for ML feature deduplication and versioning), causing downstream validation failure in Flink ML feature engineering pipeline.
AWS Resources (Deployed)
| Resource Type | Name/ID | Purpose |
|---|---|---|
| ECS Cluster | tracer-flink-cluster |
Hosts Flink batch tasks |
| ECS Task Definition | TracerFlinkEcsFlinkTaskDef |
Fargate container spec (512 CPU, 1024 MB, ARM64) |
| CloudWatch Log Group | /ecs/tracer-flink |
Flink job execution logs |
| S3 Bucket | tracerflinkecs-landingbucket23fe90fb-ztviw7xibnx7 |
Raw ingested data |
| S3 Bucket | tracerflinkecs-processedbucketde59930c-bxdsoonzx2pq |
Transformed data |
| Lambda | TriggerLambda |
Ingestion handler + ECS launcher |
| Lambda | MockApiLambda |
External vendor API simulator |
| API Gateway | https://pbjh63udyc.execute-api.us-east-1.amazonaws.com/prod/ |
HTTP trigger endpoint |
| API Gateway | https://ff1aspehx9.execute-api.us-east-1.amazonaws.com/prod/ |
Mock vendor API endpoint |
Key Differences from Prefect Test Case
| Aspect | Prefect ECS Test Case | Flink ECS Test Case |
|---|---|---|
| Orchestrator | Prefect 3.x (server + worker) | PyFlink (batch job) |
| Execution Model | Long-running service | One-shot task |
| Trigger | Prefect API / work pool | ECS RunTask API |
| State Management | Prefect server (SQLite) | Stateless |
| Container | prefecthq/prefect:3-python3.11 |
python:3.11-slim + boto3 |
| Log Group | /ecs/tracer-prefect |
/ecs/tracer-flink |
| Cluster | tracer-prefect-cluster |
tracer-flink-cluster |
| Deploy Time | ~3-5 minutes | ~60-90 seconds |
| Complexity | Higher (server + worker) | Lower (single container) |
Test Scenarios
Happy Path
POST /trigger
→ External API returns valid data (v1.0 schema)
→ ECS Flink task processes successfully
→ Data written to processed bucket
→ Task exits with code 0
Failure Path
POST /trigger?inject_error=true
→ External API returns data with schema change (v2.0, missing customer_id)
→ ECS Flink task fails validation
→ DomainError raised
→ Error logged to CloudWatch
→ Task exits with code 1
Tracer Agent Investigation Capabilities
The agent should demonstrate:
- ✅ CloudWatch Log Analysis: Parse ECS task logs
- ✅ S3 Object Inspection: Read landing/processed data
- ✅ S3 Metadata Tracing: Follow audit_key references
- ✅ Lambda Code Analysis: Inspect Trigger Lambda
- ✅ Lambda Invocation Logs: Find recent executions
- ✅ External API Audit: Retrieve and analyze vendor request/response
- ✅ Schema Comparison: Detect schema version mismatches
- ✅ Root Cause Identification: Trace failure to external API schema change
Validated Test Results (2026-01-31)
| Metric | Value |
|---|---|
| Confidence | 86% |
| Validity | 88% |
| Checks Passed | 5/5 |
Validation Checks
| Check | Status | Evidence |
|---|---|---|
| Flink logs retrieved | ✅ PASS | CloudWatch /ecs/tracer-flink |
| S3 input data inspected | ✅ PASS | Landing bucket object + metadata |
| Audit trail traced | ✅ PASS | audit/{correlation_id}.json |
| External API identified | ✅ PASS | external_api_url in audit payload |
| Schema change detected | ✅ PASS | schema_version: 2.0, missing customer_id |
Sample RCA Output
*Validated Claims (Supported by Evidence):*
• Input data contains schema version 2.0 with a truncated breaking change notification
• The S3 metadata explicitly indicates a schema change was injected
• The schema change introduced breaking modifications to customer-related fields
• The failure during module import suggests the pipeline lacks proper schema validation
*Data Lineage Flow (Evidence-Based)*
1. S3 Landing → Pipeline Executor (ECS Flink Task)
*Confidence:* 86%
*Validity Score:* 88% (7/7 validated)