duckorch
Asset-zentrierte Datenorchestrierung mit JSON-Ingestion, Partitionen, deklarativem Automation-Sensor, Snowflake-kompatiblem CREATE DYNAMIC ASSET, MCP-Server, Lineage und OpenLineage-Emission — alles auf DuckDB
Maintainer: nkwork9999
Installation und Laden
INSTALL duckorch FROM community;LOAD duckorch;Beispiel
LOAD duckorch;
-- 1. Set up state schema and register a directory of *.sql task files.PRAGMA orch_init;PRAGMA orch_register('./tasks/');
-- 2. Run the DAG (topological order, per-layer parallelism).SET orch_max_parallel = 4;PRAGMA orch_run;
-- 3. Asset-aware features (Phase 13+):PRAGMA orch_asset_list; -- all registered AssetsPRAGMA orch_asset_partitions('analytics.daily'); -- per-partition statusPRAGMA orch_backfill('analytics.daily', '2026-01-01', '2026-12-31');
-- 4. Snowflake-compatible declaration (Phase 17):PRAGMA orch_create_dynamic_asset( 'analytics.region_total', '5 minutes', 'SELECT region, SUM(total) AS rt FROM analytics.daily GROUP BY region');
-- 5. Sensor — auto-materializes when upstream updates (Phase 15):PRAGMA orch_sensor_set_interval(30);PRAGMA orch_sensor_start;
-- 6. Mermaid lineage:PRAGMA orch_visualize('lineage');
-- 7. JSON ingestion (Phase 19): nested JSON becomes flat parent/child-- tables, and later-arriving columns are absorbed automatically.PRAGMA orch_ingest_preview('orders.jsonl', 'raw.orders'); -- shape onlyPRAGMA orch_ingest_run('orders/*.jsonl', 'raw.orders');PRAGMA orch_ingest_run('orders.jsonl', 'raw.orders', disposition = 'merge', primary_key = 'id');PRAGMA orch_ingest_http('https://api.example.com/orders', 'raw.orders', secret = 'orders_api', paginate = 'cursor', records_path = 'data', cursor_path = 'meta.next', cursor_param = 'cursor');Über duckorch
duckorch ist ein DuckDB-nativer, Single-File-Asset-Orchestrator, der
die deklarative Automation von Dagster und Snowflakes
Semantik von CREATE DYNAMIC TABLE in ein LOAD duckorch; bringt. Ausgelegt,
auf einem Laptop oder im Flugzeug ohne Cloud-Control-Plane zu laufen.
Aufgabendefinition (SQLMesh-artige Header in einfachen .sql-Dateien):
-- @asset name=analytics.user_stats-- @asset_group sales-- @partitions_by daily(start=2026-01-01)-- @param partition_key:DATE-- @automation eager AND NOT in_progress()-- @freshness max_lag=60min-- @check name=positive "SELECT MIN(rev) FROM ${asset}" expect gt 0
CREATE OR REPLACE TABLE analytics.user_stats ASSELECT country, SUM(rev) AS revFROM analytics.clean_usersWHERE event_date = $partition_keyGROUP BY country;Eingaben werden automatisch über sqlparser-rs extrahiert. $partition_key wird über
DuckDB PREPARE gebunden (mehranweisungsfähig).
Fähigkeiten:
-
Tasks + DAG (Phase 0–9): verzeichnisgeladene SQL-Dateien, topologische Ausführung, Parallelität pro Schicht, Exponential-Backoff-Retry, Downstream- Skip,
@test, Mermaid (lineage/dag/combined), OpenLineage- Ereignisse, tabellen- und spaltenweise Lineage mit Subtyp-Taxonomie, optionale Ad-hoc-Abfrageerfassung, DuckLake-bewusster OL-Namespace. -
MCP-Server (Phase 11):
duck-orch-mcp-stdio-Server (rmcp 0.3) mit 9 Tools für die Claude-Code-Integration (list_assets,run_pipelinemit Standarddry_runusw.). -
Asset (Phase 13):
@asset-Header befördern Ausgaben zu erstklassigen Assets in__orch__.assetsmit Materialisierungshistorie, code_version- Hash und deklarierten Kanten. Abwärtskompatibel mit@outputs. -
Partition (Phase 14):
@partitions_by daily/static/multi, Bindung von$partition_key,orch_backfill, kalenderartige ✅⚪-ASCII-Ansicht. -
AutomationCondition + Sensor (Phase 15): DSL (
eager / on_cron / on_missing / freshness_violated / in_progress&/|/!),@target_lag-Drossel, Hintergrund-std::thread- Sensor, der pollt undRunSingleTaskautomatisch auslöst, wenn Bedingungen erfüllt sind.
-
Freshness + Asset Check (Phase 16):
@freshness max_lag=...,@check name=N "<SQL>" expect <op> <value>mit automatischem Lauf bei Erfolg undseverity=error, das Downstream blockiert. -
Snowflake
CREATE DYNAMIC ASSET(Phase 17):PRAGMA orch_create_dynamic_asset(name, target_lag, sql)synthetisiert Asset +automation_condition='eager()', sodass der Sensor es aufnimmt. Die CLIduck-orch dynamic migrate-from-snowflake <dump>parst Snowflake- Dumps und registriert jeden Block (überspringtWAREHOUSE/REFRESH_MODE). -
JSON-Ingestion (Phase 19):
orch_ingest_run/orch_ingest_httpnormalisieren verschachteltes JSON in Parent-/Child-Tabellen (Structs werden in den Parent geflacht, Arrays werden zu Child-Tabellen, verknüpft über_orch_parent_id/_orch_index). Ein Schema-Ledger versioniert jede Form und nimmt hinzugefügte Spalten und erweiternde Typen überALTERauf; inkompatible Änderungen lassen den Load mit benannter Spalte fehlschlagen. Schreibdispositionenappend/replace/merge(primary_key-gesteuert, Kinder eingeschlossen). HTTP-Quellen unterstützenpage/offset/cursor/link-Pagination, Bearer-Tokens aus einem DuckDB-Secret, Resume-Cursor und eine gemeldete Seitenobergrenze. Ein dreiteiliges Ziel (lake.raw.orders) lädt in einen angehängten Katalog, sodass DuckLake nur ein weiteres Ziel ist. Geladene Tabellen registrieren sich als Assets mit Lineage zurück zur Quell-URI.
3-Wege-Oberfläche: jede Funktion erreichbar über CLI (duck-orch ...),
SQL (PRAGMA orch_*) und MCP (Claude Code).
Begleit-CLI: duck-orch mit den Unterbefehlen register / run / status / graph / test / validate / impact / lineage / schedule / asset / backfill / automation / sensor / check / dynamic, alle --json-fähig.
Zustandstabellen: __orch__.{tasks, runs, lineage_edges, column_lineage, task_edges, tests, schedules, assets, asset_materializations, asset_edges, asset_partitions, automation_evaluations, asset_checks, asset_check_results, ingest_schemas, ingest_schema_changes, ingest_loads, ingest_state, ingest_fetches}.
Architektur: dünner C++-Shim (ca. 3000 Zeilen, registriert PRAGMAs, führt SQL über eine Connection pro Thread aus, hostet den Sensor-Thread, stellt OptimizerExtension für Ad-hoc-Erfassung bereit) plus ein Rust-Workspace (orch_common / orch_dag / orch_lineage / orch_runtime / orch_ol / orch_ingest / orch_core / orch_cli / orch_mcp), der die gesamte Logik in Rust hält, während die C++-Schicht DuckDB-interne Aufrufe übernimmt.
Hinzugefügte Funktionen
| function_name | function_type | description | comment | examples |
|---|---|---|---|---|
| orch_asset_health | pragma | NULL | NULL | |
| orch_asset_lineage | pragma | NULL | NULL | |
| orch_asset_list | pragma | NULL | NULL | |
| orch_asset_list_group | pragma | NULL | NULL | |
| orch_asset_materializations | pragma | NULL | NULL | |
| orch_asset_partitions | pragma | NULL | NULL | |
| orch_asset_partitions_calendar | pragma | NULL | NULL | |
| orch_asset_show | pragma | NULL | NULL | |
| orch_automation_simulate | pragma | NULL | NULL | |
| orch_automation_status | pragma | NULL | NULL | |
| orch_backfill | pragma | NULL | NULL | |
| orch_backfill_missing | pragma | NULL | NULL | |
| orch_build_dag | scalar | NULL | NULL | |
| orch_check_history | pragma | NULL | NULL | |
| orch_check_run | pragma | NULL | NULL | |
| orch_create_dynamic_asset | pragma | NULL | NULL | |
| orch_downstream_of | scalar | NULL | NULL | |
| orch_dynamic_list | pragma | NULL | NULL | |
| orch_dynamic_refresh | pragma | NULL | NULL | |
| orch_extract_io | scalar | NULL | NULL | |
| orch_hello | scalar | NULL | NULL | |
| orch_ingest_http | pragma | NULL | NULL | |
| orch_ingest_preview | pragma | NULL | NULL | |
| orch_ingest_reset | pragma | NULL | NULL | |
| orch_ingest_run | pragma | NULL | NULL | |
| orch_ingest_state | pragma | NULL | NULL | |
| orch_init | pragma | NULL | NULL | |
| orch_load_directory_json | scalar | NULL | NULL | |
| orch_parse_task | scalar | NULL | NULL | |
| orch_register | pragma | NULL | NULL | |
| orch_render_mermaid | scalar | NULL | NULL | |
| orch_restate | pragma | NULL | NULL | |
| orch_run | pragma | NULL | NULL | |
| orch_run_partition | pragma | NULL | NULL | |
| orch_sensor_set_interval | pragma | NULL | NULL | |
| orch_sensor_start | pragma | NULL | NULL | |
| orch_sensor_status | pragma | NULL | NULL | |
| orch_sensor_stop | pragma | NULL | NULL | |
| orch_test | pragma | NULL | NULL | |
| orch_visualize | pragma | NULL | NULL |
Überladene Funktionen
Diese Erweiterung fügt keine Funktionsüberladungen hinzu.
Hinzugefügte Typen
Diese Erweiterung fügt keine Typen hinzu.
Hinzugefügte Einstellungen
| name | description | input_type | scope | aliases |
|---|---|---|---|---|
| orch_capture_interactive | Capture column lineage for ad-hoc INSERT/CTAS queries via ParserExtension | BOOLEAN | GLOBAL | [] |
| orch_max_parallel | Maximum parallel tasks per DAG layer | BIGINT | GLOBAL | [] |
| orch_namespace | Job namespace for OpenLineage events | VARCHAR | GLOBAL | [] |
| orch_openlineage_api_key | OpenLineage API key | VARCHAR | GLOBAL | [] |
| orch_openlineage_debug | Log OpenLineage events to stderr | BOOLEAN | GLOBAL | [] |
| orch_openlineage_url | OpenLineage backend URL (e.g. http://localhost:5000/api/v1/lineage) | VARCHAR | GLOBAL | [] |