927437a8d8
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI: - list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals + runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId. - list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables. - wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console (preserva ancho del sidebar), tmux_map_claude_panes. - launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r, mouse on, remain-on-exit off; fija el ancho del sidebar con hooks. - docs/capabilities/claude-fleet.md + entrada en el INDEX. Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes varios de docs e infra de otra sesion, agrupados aqui para no perderlos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.1 KiB
7.1 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| duckdb_to_postgres | pipeline | py | pipelines | 1.0.0 | impure | def duckdb_to_postgres(duckdb_path: str, table: str, pg_dsn: str, pg_table: str = None, mode: str = 'replace', key_cols: list = None, batch_size: int = 5000) -> dict | Pipeline que sincroniza una tabla DuckDB a PostgreSQL. Es lo que desbloquea que herramientas BI (Metabase, Grafana, Superset) lean datos que viven en DuckDB, porque NO hablan DuckDB nativo pero todas hablan PostgreSQL. Pasos: (a) lee el schema con duckdb_table_schema; (b) mapea tipos DuckDB->PostgreSQL (BIGINT/INTEGER->BIGINT, DOUBLE/FLOAT->DOUBLE PRECISION, VARCHAR/TEXT->TEXT, BOOLEAN->BOOLEAN, DATE->DATE, TIMESTAMP->TIMESTAMP, resto->TEXT) y genera CREATE TABLE IF NOT EXISTS con PRIMARY KEY si key_cols (DROP TABLE IF EXISTS antes si mode='replace'), aplicandolo con pg_apply_sql; (c) lee las filas con duckdb_query_readonly paginando con LIMIT/OFFSET e inserta en PostgreSQL con pg_insert_rows (add_snapshot_date=False) en lotes de batch_size, o con pg_upsert si hay key_cols y mode!='replace'. pg_upsert se importa detras de un check de import: sin el, el camino upsert no esta disponible pero replace/append funcionan. Compone funciones del registry sin reescribir su logica. Devuelve un dict sin lanzar: {status:'ok', pg_table, rows_synced, created} en exito y {status:'error', error} en fallo. Depende de duckdb (1.5.2) y psycopg2. |
|
|
false | error_py_core |
|
|
dict. En exito: {status:'ok', pg_table:str, rows_synced:int, created:bool} donde rows_synced es el total de filas volcadas y created indica si se ejecuto el CREATE/DROP del schema. En error (sin lanzar): {status:'error', error:str}. | true |
|
python/functions/pipelines/duckdb_to_postgres_test.py | python/functions/pipelines/duckdb_to_postgres.py |
Ejemplo
import sys
sys.path.insert(0, "python/functions")
from pipelines.duckdb_to_postgres import duckdb_to_postgres
# Snapshot completo: reemplaza la tabla destino en PostgreSQL con todas las filas
# de la tabla DuckDB. Metabase/Grafana ya pueden leerla.
res = duckdb_to_postgres(
"/tmp/almacen.duckdb",
"ventas",
"postgresql://captacion:****@127.0.0.1:5433/trends",
pg_table="ventas_diario",
mode="replace",
)
print(res)
# {'status': 'ok', 'pg_table': 'ventas_diario', 'rows_synced': 1280, 'created': True}
# Sync idempotente por clave: no duplica filas en re-ejecuciones.
res2 = duckdb_to_postgres(
"/tmp/almacen.duckdb",
"clientes",
"postgresql://captacion:****@127.0.0.1:5433/trends",
mode="upsert",
key_cols=["id"],
)
print(res2) # {'status': 'ok', 'pg_table': 'clientes', 'rows_synced': 540, 'created': True}
Cuando usarla
Cuando tienes datos en un archivo DuckDB y necesitas que una herramienta BI los
lea: Metabase, Grafana y Superset NO hablan DuckDB nativo, pero todas hablan
PostgreSQL. Es el ultimo eslabon del flujo Excel -> DuckDB -> PostgreSQL
(precedido por excel_to_duckdb_py_infra). Usa mode='replace' para refrescos
completos programados (un snapshot diario que recrea la tabla) y
mode='upsert' + key_cols para sincronizaciones incrementales idempotentes que no
duplican filas al re-ejecutar.
Gotchas
- DuckDB es single-writer: el pipeline abre la base en read_only para leer, pero si otro proceso la tiene bloqueada en escritura con version distinta del motor, la apertura puede fallar; el error se devuelve en el dict, no se lanza.
- El modo read_only exige que el archivo DuckDB exista: no lo crea. Un
duckdb_pathinexistente devuelve{status:'error', ...}ya en el paso (a). - Mapeo de tipos con posible perdida: el mapeo DuckDB->PostgreSQL es conservador.
Tipos no contemplados (DECIMAL con escala, HUGEINT/UBIGINT de 128 bits, LIST/STRUCT/
MAP) caen a TEXT. Si el tipado fuerte importa aguas abajo (agregaciones numericas
en Metabase), revisa el schema con
duckdb_table_schema_py_infray ajusta los tipos en DuckDB antes de sincronizar. mode='replace'es destructivo: haceDROP TABLE IF EXISTSsobre la tabla PostgreSQL destino antes de recrearla. Cualquier dato o indice manual de esa tabla se pierde. Para sincronizaciones que deban preservar la tabla existente usamode='append'/'upsert'(CREATE TABLE IF NOT EXISTS, sin DROP).pg_upsertopcional: se importa detras de un check de import. Sipg_upsert_py_infrano esta en el entorno,mode != 'replace'conkey_colsdevuelve{status:'error', ...}explicando que falta; el camino replace/append (sin upsert) sigue funcionando.- Upsert requiere PRIMARY KEY o UNIQUE sobre las
key_colsen PostgreSQL para queON CONFLICTfuncione. El pipeline crea esa PRIMARY KEY en el CREATE cuando pasaskey_cols; si la tabla ya existia sin esa restriccion (mode!='replace'y tabla preexistente), el upsert fallara — recrea conmode='replace' + key_colsuna vez. - Snapshot no transaccional entre lectura y escritura: la lectura paginada de DuckDB y la escritura a PostgreSQL no comparten transaccion. Si la tabla DuckDB cambia a mitad del volcado (otro escritor), el resultado en PostgreSQL puede mezclar estados. Sincroniza desde una base DuckDB estable (no mientras se ingesta).
pg_insert_rowsypg_apply_sqllanzan RuntimeError internamente; el pipeline los envuelve en try/except y convierte el fallo a{status:'error', ...}. Nunca propaga la excepcion al caller.