Skip to main content 首页 创作者 ffsshhttiikk opencode-agents-skills etl-pipelines
etl-pipelines Extract, Transform, Load (ETL) pipeline design and implementation for moving data from source systems, transforming it to meet requirements, and loading it into target systems for analysis.
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ffsshhttiikk/opencode-agents-skills --skill etl-pipelines命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... name etl-pipelines description Extract, Transform, Load (ETL) pipeline design and implementation for moving data from source systems, transforming it to meet requirements, and loading it into target systems for analysis. category data-science keywords ["etl-pipelines","data pipelines","data engineering","data transformation","data integration","workflow orchestration","apache airflow","dag"] difficulty intermediate related_skills ["pandas","big-data","data-visualization"]
ETL Pipelines
What I do
I provide frameworks and patterns for building robust data pipelines that extract data from various sources, transform it to meet business requirements, and load it into target systems. I ensure data quality, enable scheduled execution, and provide monitoring and error handling capabilities for production data workflows.
When to use me
Moving data from operational databases to data warehouses
Consolidating data from multiple sources
Creating data lakes from raw data
Building feature stores for machine learning
Scheduling regular data refreshes
Implementing data quality checks
Building real-time streaming pipelines
Creating data aggregation workflows
Core Concepts
Pipeline Components
Extract : Pull data from source systems (databases, APIs, files)
Transform : Clean, validate, enrich, aggregate data
Load : Write data to destination systems
Orchestrate : Manage dependencies and scheduling
Data Quality
Schema validation : Verify structure matches expectations
Data type checks : Ensure correct types
Range checks : Validate value ranges
Uniqueness checks : Detect duplicate records
Referential integrity : Verify relationships
Orchestration
DAGs : Directed Acyclic Graphs for dependency management
Task dependencies : Define execution order
Failure handling : Retries, alerts, dead letter queues
Backfilling : Re-processing historical data
Tools
Apache Airflow : Workflow orchestration
Prefect/Dagster : Modern orchestration frameworks
Luigi : Spotify's pipeline framework
dbt : Data transformation tool
Code Examples (Python)
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import logging
class BasicETL :
def __init__ (self, source_conn, target_conn ):
self .source = source_conn
self .target = target_conn
self .logger = logging.getLogger(__name__)
def extract (self, query, params=None ):
"""Extract data from source."""
self .logger.info(f"Extracting data with query: {query[:100 ]} ..." )
df = pd.read_sql(query, self .source, params=params)
self .logger.info(f"Extracted {len (df)} rows" )
return df
def transform (self, df ):
"""Transform data."""
self .logger.info(f"Transforming {len (df)} rows..." )
df.columns = [c.strip().lower().replace(' ' , '_' ) for c in df.columns]
df = df.fillna({
: ,
: ,
: pd.NaT
})
df[ ] = pd.to_datetime(df[ ], errors= )
df[ ] = pd.to_numeric(df[ ], errors= )
df = df.drop_duplicates(subset=[ ])
df[ ] = datetime.now()
df = df[df[ ] >= ]
df
( ):
.logger.info( )
df.to_sql(table_name, .target, if_exists=if_exists, index= )
.logger.info( )
( ):
:
df = .extract(extract_query)
df = .transform(df)
transform_func:
df = transform_func(df)
.load(df, target_table)
Exception e:
.logger.error( )
:
( ):
col, dtype expected_schema.items():
col df.columns:
ValueError( )
df[col].dtype != dtype:
TypeError( )
( ):
min_val (df[col] < min_val). ():
invalid = (df[col] < min_val). ()
ValueError( )
max_val (df[col] > max_val). ():
invalid = (df[col] > max_val). ()
ValueError( )
( ):
duplicates = df[col].duplicated(). ()
duplicates > :
ValueError( )
( ):
col required_cols:
completeness = df[col].notna().mean()
completeness < threshold:
ValueError( )
:
( ):
.source = source
.target = target
( ):
:
query =
result = pd.read_sql(query, .target)
result[ ].iloc[ ] (result) >
:
( ):
log_df = pd.DataFrame([{
: table_name,
: rows_processed,
: status,
: datetime.now()
}])
log_df.to_sql( , .target, if_exists= , index= )
( ):
last_run = .get_last_processed(table_name)
last_run:
query = extract_query_template. (watermark= )
:
query = extract_query_template. (watermark= )
df = pd.read_sql(query, .source)
(df) == :
.logger.info( )
df = .transform(df)
.load(df, table_name, if_exists= )
.log_etl(table_name, (df), )
df
Transform single record. Process streaming records.
Best Practices
Design for failure : Assume any component can fail; implement retries, logging, and alerts.
Incremental over full reload : Process only new/changed data when possible for efficiency.
Idempotent operations : Running the pipeline multiple times should produce the same result.
Separate concerns : Keep extraction, transformation, and loading logic independent.
Metadata management : Track data lineage, schema versions, and processing timestamps.
Monitor data quality : Implement validation at each stage with alerting.
Handle schema evolution : Plan for schema changes without breaking pipelines.
Document data contracts : Define clear interfaces between pipeline stages.
Common Patterns
Pattern 1: Resilient Batch ETL
class ResilientETL :
def __init__ (self, config ):
self .config = config
self .max_retries = 3
self .backoff_factor = 2
def run_with_retry (self, task_name, task_func, **kwargs ):
"""Run task with exponential backoff retry."""
for attempt in range (self .max_retries):
try :
return task_func(**kwargs)
except Exception as e:
if attempt == self .max_retries - 1 :
self .send_alert(task_name, e)
raise
sleep_time = self .backoff_factor ** attempt
self .logger.warning(f"Task {task_name} failed, retrying in {sleep_time} s" )
sleep(sleep_time)
def checkpoint (self, stage, state ):
"""Save pipeline state for recovery."""
checkpoint_df = pd.DataFrame([{
'stage' : stage,
'state' : json.dumps(state),
'timestamp' : datetime.now()
}])
checkpoint_df.to_sql('pipeline_checkpoints' ,
self .checkpoint_db,
if_exists= )
( ):
query =
pd.read_sql(query, .checkpoint_db).iloc[ ][ ]
Pattern 2: Data Quality Framework
class DataQualityFramework :
def __init__ (self ):
self .checks = []
def add_check (self, name, check_func, severity='error' ):
"""Add quality check."""
self .checks.append({'name' : name, 'func' : check_func, 'severity' : severity})
def run_checks (self, df, context ):
"""Execute all quality checks."""
results = []
for check in self .checks:
try :
passed = check['func' ](df, context)
results.append({
'check' : check['name' ],
'passed' : passed,
'severity' : check['severity' ]
})
except Exception as e:
results.append({
'check' : check['name' ],
'passed' : False ,
'error' : str (e),
'severity' : check['severity' ]
})
errors = [r for r in results if not r[ ] r[ ] == ]
errors:
DataQualityError(errors)
results
():
framework = DataQualityFramework()
framework.add_check( ,
df, ctx: df.isnull(). (). () == )
framework.add_check( ,
df, ctx: (df.columns) == (ctx[ ]))
framework.add_check( ,
df, ctx: (df[ctx[ ]] >= ). (). ())
framework.add_check( ,
df, ctx: df.duplicated(). () == )
framework
Pattern 3: Feature Engineering Pipeline
class FeatureEngineeringPipeline :
def __init__ (self, feature_store ):
self .feature_store = feature_store
self .transformations = []
def add_feature (self, name, source_col, transform_func ):
"""Add feature transformation."""
self .transformations.append({
'name' : name,
'source' : source_col,
'func' : transform_func
})
def build_features (self, df, timestamp_col='timestamp' ):
"""Build all features for a dataset."""
features_df = df.copy()
for feat in self .transformations:
features_df[feat['name' ]] = feat['func' ](features_df[feat['source' ]])
features_df['hour' ] = features_df[timestamp_col].dt.hour
features_df['day_of_week' ] = features_df[timestamp_col].dt.dayofweek
features_df['is_weekend' ] = features_df['day_of_week' ].isin([5 , 6 ]).astype(int )
features_df = self .add_rolling_features(features_df, 'value' , '1h' , '24h' )
return features_df
def ( ):
window windows:
df[ ] = df.groupby( )[col].transform(
x: x.rolling(window, min_periods= ).mean()
)
df
( ):
.feature_store.save(
entity_id=entity_id,
features=features_df.to_dict(orient= ),
timestamp=timestamp
)
'numeric_col'
0
'string_col'
'unknown'
'date_col'
'date_col'
'date_col'
'coerce'
'numeric_col'
'numeric_col'
'coerce'
'id'
'processed_at'
'value'
0
return
def
load
self, df, table_name, if_exists='append'
"""Load data to target."""
self
f"Loading {len (df)} rows to {table_name} ..."
self
False
self
f"Successfully loaded {len (df)} rows"
def
run
self, extract_query, target_table, transform_func=None
"""Execute full ETL pipeline."""
try
self
self
if
self
return
True
except
as
self
f"ETL failed: {e} "
raise
class
DataValidator
@staticmethod
def
validate_schema
df, expected_schema
"""Validate DataFrame schema."""
for
in
if
not
in
raise
f"Missing column: {col} "
if
raise
f"Column {col} has wrong type: {df[col].dtype} vs {dtype} "
@staticmethod
def
validate_range
df, col, min_val=None , max_val=None
"""Validate values in range."""
if
is
not
None
and
any
sum
raise
f"{col} has {invalid} values below {min_val} "
if
is
not
None
and
any
sum
raise
f"{col} has {invalid} values above {max_val} "
@staticmethod
def
validate_uniqueness
df, col
"""Check for duplicates."""
sum
if
0
raise
f"Column {col} has {duplicates} duplicates"
@staticmethod
def
validate_completeness
df, required_cols, threshold=0.99
"""Check completeness of required columns."""
for
in
if
raise
f"Column {col} has only {completeness:.2 %} completeness"
class
IncrementalETL
def
__init__
self, source, target
self
self
def
get_last_processed
self, table_name
"""Get timestamp of last successful load."""
try
f"SELECT MAX(processed_at) as last_run FROM etl_log WHERE table_name = '{table_name} '"
self
return
'last_run'
0
if
len
0
else
None
except
return
None
def
log_etl
self, table_name, rows_processed, status
"""Log ETL execution."""
'table_name'
'rows_processed'
'status'
'run_time'
'etl_log'
self
'append'
False
def
run_incremental
self, table_name, watermark_col, extract_query_template
"""Run incremental ETL based on watermark."""
self
if
format
f"WHERE {watermark_col} > '{last_run} '"
else
format
""
self
if
len
0
self
"No new data to process"
return
self
self
'append'
self
len
'success'
return
"""
from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.operators.postgres_operator import PostgresOperator
from datetime import datetime, timedelta
default_args = {
'owner': 'data_team',
'depends_on_past': False,
'start_date': datetime(2024, 1, 1),
'email_on_failure': True,
'email_on_retry': False,
'retries': 3,
'retry_delay': timedelta(minutes=5),
}
dag = DAG(
'daily_etl_pipeline',
default_args=default_args,
description='Daily ETL pipeline for data warehouse',
schedule_interval='0 2 * * *', # Run at 2 AM daily
catchup=False,
)
def extract_sales(**context):
from sqlalchemy import create_engine
engine = create_engine(context['connection']['sales_db'])
df = pd.read_sql("SELECT * FROM sales", engine)
df.to_csv('/tmp/sales_raw.csv', index=False)
return '/tmp/sales_raw.csv'
def transform_sales(**context):
df = pd.read_csv(context['task_instance'].xcom_pull(task_ids='extract_sales'))
df['date'] = pd.to_datetime(df['date'])
df['revenue'] = df['quantity'] * df['price']
df.to_parquet('/tmp/sales_transformed.parquet', index=False)
return '/tmp/sales_transformed.parquet'
def load_warehouse(**context):
df = pd.read_parquet(context['task_instance'].xcom_pull(task_ids='transform_sales'))
engine = create_engine(context['connection']['warehouse'])
df.to_sql('daily_sales', engine, if_exists='append', index=False)
extract_task = PythonOperator(
task_id='extract_sales',
python_callable=extract_sales,
provide_context=True,
dag=dag,
)
transform_task = PythonOperator(
task_id='transform_sales',
python_callable=transform_sales,
provide_context=True,
dag=dag,
)
load_task = PythonOperator(
task_id='load_warehouse',
python_callable=load_warehouse,
provide_context=True,
dag=dag,
)
extract_task >> transform_task >> load_task
"""
"""
from kafka import KafkaConsumer, KafkaProducer
import json
class StreamingETL:
def __init__(self, kafka_brokers, input_topic, output_topic):
self.consumer = KafkaConsumer(
input_topic,
bootstrap_servers=kafka_brokers,
value_deserializer=lambda x: json.loads(x.decode('utf-8'))
)
self.producer = KafkaProducer(
bootstrap_servers=kafka_brokers,
value_serializer=lambda x: json.dumps(x).encode('utf-8')
)
def transform_record(self, record):
"""
"""
return {
'id': record['id'],
'timestamp': datetime.now().isoformat(),
'value_normalized': (record['value'] - record['mean']) / record['std'],
'category': record['category'].upper()
}
def run(self):
"""
"""
for message in self.consumer:
record = message.value
transformed = self.transform_record(record)
self.producer.send(output_topic, value=transformed)
"""
'append'
def
resume_from_checkpoint
self, stage
"""Resume pipeline from last checkpoint."""
f"SELECT * FROM pipeline_checkpoints WHERE stage = '{stage} ' ORDER BY timestamp DESC LIMIT 1"
return
self
0
'state'
'passed'
and
'severity'
'error'
if
raise
return
@staticmethod
def
standard_checks
"""Create standard quality checks."""
'null_check'
lambda
sum
sum
0
'schema_check'
lambda
set
set
'expected_columns'
'range_check'
lambda
'numeric_cols'
0
all
all
'duplicate_check'
lambda
sum
0
return
add_rolling_features
self, df, col, *windows
"""Add rolling window features."""
for
in
f'{col} _rolling_{window} _mean'
'id'
lambda
1
return
def
save_to_store
self, entity_id, features_df, timestamp
"""Save features to feature store."""
self
'records'