Files
wehub-resource-sync 4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

113 lines
4.3 KiB
Python
Vendored

"""
Upstream/Downstream Pipeline - Orchestration Layer.
Follows Senior/Staff-level refactoring principles:
1. Split domain logic from infrastructure (domain.py).
2. Introduce explicit error types (errors.py).
3. Thin, testable adapters for S3 and Alerting (adapters/).
4. Explicit schemas and contracts (schemas.py).
5. File layout optimized for intent.
"""
import json
from contextlib import contextmanager
from .adapters.alerting import fire_pipeline_alert
from .adapters.s3 import read_json, write_json
from .config import PIPELINE_NAME, PROCESSED_BUCKET, REQUIRED_FIELDS
from .domain import transform_data as domain_transform_data
from .domain import validate_data as domain_validate_data
from .errors import PipelineError
class _NoopSpan:
def set_attribute(self, *_args, **_kwargs) -> None:
return None
class _NoopTracer:
@contextmanager
def start_as_current_span(self, *_args, **_kwargs):
yield _NoopSpan()
def lambda_handler(event, context):
"""
Entrypoint: Adapts S3 events to Domain Logic.
Responsibilities:
- Extract infrastructure details (bucket, key).
- Coordinate adapters and domain logic.
- Centralized error handling and alerting.
"""
tracer = _NoopTracer()
correlation_id = "unknown"
for record in event.get("Records", []):
bucket = record["s3"]["bucket"]["name"]
key = record["s3"]["object"]["key"]
with tracer.start_as_current_span("process_s3_record") as span:
span.set_attribute("s3.bucket", bucket)
span.set_attribute("s3.key", key)
try:
# 1. Extraction (Infrastructure)
raw_payload, correlation_id = read_json(bucket, key)
raw_records = raw_payload.get("data", [])
span.set_attribute("record_count", len(raw_records))
span.set_attribute("correlation_id", correlation_id)
execution_run_id = correlation_id
span.set_attribute("execution.run_id", execution_run_id)
# Log structured input for traceability
print(
json.dumps(
{
"event": "processing_started",
"input_bucket": bucket,
"input_key": key,
"correlation_id": correlation_id,
"execution_run_id": execution_run_id,
"record_count": len(raw_records),
}
)
)
# 2. Processing (Domain Logic - Pure)
with tracer.start_as_current_span("validate_data") as validate_span:
validate_span.set_attribute("execution.run_id", execution_run_id)
validate_span.set_attribute("record_count", len(raw_records))
validate_span.set_attribute("correlation_id", correlation_id)
domain_validate_data(raw_records, REQUIRED_FIELDS)
with tracer.start_as_current_span("transform_data") as transform_span:
transform_span.set_attribute("execution.run_id", execution_run_id)
transform_span.set_attribute("record_count", len(raw_records))
transform_span.set_attribute("correlation_id", correlation_id)
processed_records = domain_transform_data(raw_records)
# 3. Loading (Infrastructure)
output_key = key.replace("ingested/", "processed/")
output_payload = {"data": [r.to_dict() for r in processed_records]}
write_json(
bucket=PROCESSED_BUCKET,
key=output_key,
data=output_payload,
correlation_id=correlation_id,
source_key=key,
)
except PipelineError as e:
# Domain or System errors caught and alerted
fire_pipeline_alert(PIPELINE_NAME, bucket, key, correlation_id, e)
raise
except Exception as e:
# Unexpected system-level crashes
fire_pipeline_alert(PIPELINE_NAME, bucket, key, correlation_id, e)
raise
return {"status": "success", "correlation_id": correlation_id}