data_drain 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/skill/SKILL.md CHANGED
@@ -8,12 +8,14 @@ Skill de conocimiento completo sobre DataDrain. Consultame para cualquier pregun
8
8
  - **Engine** — Motor principal que orquesta el flujo Conteo → Export → Verify → Purge.
9
9
  - **FileIngestor** — Convierte archivos crudos (CSV/JSON/Parquet) a Parquet particionado en el Data Lake.
10
10
  - **Record** — Clase base ORM analítico (tipo ActiveRecord) read-only sobre Parquet vía DuckDB.
11
- - **GlueRunner** — Orquestador de AWS Glue Jobs para tablas de gran volumen (>500GB-1TB).
11
+ - **GlueRunner** — Orquestador de AWS Glue Jobs para tablas de gran volumen (>500GB-1TB). Soporta lifecycle completo: crear, actualizar, eliminar y verificar jobs.
12
12
  - **Storage Adapter** — Patrón Strategy con dos implementaciones: `Storage::Local` y `Storage::S3`. Cacheado en `Storage.adapter`.
13
13
  - **Observability** — Módulo mixín (`include`/`extend`) con `safe_log` resiliente y logging KV estructurado.
14
14
  - **Hive Partitioning** — Estructura de carpetas `key1=val1/key2=val2/...` que DuckDB genera y consume nativamente para prefix scans eficientes.
15
15
  - **Semi-abierto** — Convención de rangos `[start, end)` con `<` (no `<=`) para evitar pérdida de microsegundos en límites de fecha.
16
16
  - **skip_export** — Modo del Engine donde delega export a herramienta externa (Glue/EMR) y solo verifica + purga.
17
+ - **ensure_job** — Wrapper idempotente de GlueRunner que crea o actualiza un job según config deseada. Incluye diffing de configuración para evitar API calls innecesarios.
18
+ - **changed_fields** — Helper privado de ensure_job que compara config deseada vs actual de un Glue Job y retorna qué campos difieren.
17
19
  - **Heartbeat** — Log de progreso emitido cada 100 lotes en purgas masivas (tablas 1TB).
18
20
  - **Wispro-Observability-Spec v1** — Estándar de logs KV: `component=` y `event=` primero, sufijo `_s` para tiempos float, `_count` para enteros, sin unidades en valores.
19
21
 
@@ -66,9 +68,9 @@ DataDrain resuelve el ciclo de vida de datos históricos en bases relacionales c
66
68
 
67
69
  ### Stack y dependencias
68
70
 
69
- - Ruby `>= 3.0.0`
71
+ - Ruby `>= 3.2.0`
70
72
  - Runtime: `activemodel >= 6.0`, `duckdb ~> 1.4`, `pg >= 1.2`, `aws-sdk-s3 ~> 1.114`, `aws-sdk-glue ~> 1.0`
71
- - Versión actual: `0.1.19`
73
+ - Versión actual: `0.5.1`
72
74
 
73
75
  ## API Pública (resumen)
74
76
 
@@ -123,6 +125,35 @@ ArchivedX.destroy_all(isp_id: 42) # => Integer (pa
123
125
 
124
126
  # 4. Glue para tablas 1TB+
125
127
  DataDrain::GlueRunner.run_and_wait("job-name", { "--key" => "val" }, polling_interval: 30)
128
+
129
+ # 4b. Glue Jobs Lifecycle (v0.4.0+)
130
+ # Verificar si existe
131
+ DataDrain::GlueRunner.job_exists?("my-job") # => true/false
132
+
133
+ # Obtener config completa
134
+ job = DataDrain::GlueRunner.get_job("my-job") # => Aws::Glue::Types::Job
135
+
136
+ # Crear job con script local (v0.5.0+)
137
+ job = DataDrain::GlueRunner.create_job(
138
+ "my-job",
139
+ role_arn: "arn:aws:iam::123:role/GlueRole",
140
+ script_path: "scripts/glue/export.py", # local → S3 automático
141
+ script_bucket: "my-bucket",
142
+ script_folder: "scripts",
143
+ timeout: 1440,
144
+ max_retries: 2
145
+ )
146
+
147
+ # Upsert idempotente con diffing de config
148
+ job = DataDrain::GlueRunner.ensure_job(
149
+ "my-job",
150
+ role_arn: "arn:aws:iam::123:role/GlueRole",
151
+ script_path: "scripts/glue/export.py",
152
+ script_bucket: "my-bucket"
153
+ )
154
+
155
+ # Eliminar job (idempotente)
156
+ DataDrain::GlueRunner.delete_job("my-job") # => true/false
126
157
  ```
127
158
 
128
159
  Detalle completo de firmas, parámetros, retornos y comportamientos en [API Detallada](references/api-detallada.md).
@@ -172,6 +203,28 @@ No. La gema NO emite `source=` manualmente — lo inyecta automáticamente `exis
172
203
 
173
204
  `component=data_drain event=<clase>.<suceso> [campos KV]`. Tiempos con sufijo `_s` y valor float. Contadores con `_count` y valor integer. Sin unidades en los valores. Detalle en [Eventos y Telemetría](references/eventos-telemetria.md).
174
205
 
206
+ ### ¿Cómo subo un script Glue desde mi repo?
207
+
208
+ Desde v0.5.0 podés usar `script_path:` en lugar de `script_location:`:
209
+
210
+ ```ruby
211
+ DataDrain::GlueRunner.ensure_job(
212
+ "my-export-job",
213
+ script_path: "scripts/glue/export.py",
214
+ script_bucket: "my-bucket",
215
+ script_folder: "scripts",
216
+ role_arn: ENV["GLUE_ROLE_ARN"]
217
+ )
218
+ ```
219
+
220
+ La gema sube el script a S3 usando el `Storage::S3` adapter existente
221
+ (con `credential_chain` si tenés IAM role). **Requiere `storage_mode = :s3`**.
222
+ Si `storage_mode = :local`, levanta `ConfigurationError`.
223
+
224
+ **Overwrite:** cada invocación sobrescribe el archivo en S3. Útil para que
225
+ el script siga al código del repo. Si necesitás versionar, usar `script_filename:`
226
+ con hash o timestamp.
227
+
175
228
  ## Errores
176
229
 
177
230
  Catálogo top. Detalle completo y resolución en [API Detallada](references/api-detallada.md).
@@ -197,6 +250,12 @@ Errores de query DuckDB. En `Engine#verify_integrity` se captura y se loguea com
197
250
  ### `RuntimeError` desde `GlueRunner`
198
251
  Levantado cuando un Job de Glue termina con estado `FAILED`, `STOPPED` o `TIMEOUT`. **Mensaje:** `"Glue Job <name> (Run ID: <id>) falló con estado <status>."`
199
252
 
253
+ ### `Aws::Glue::Errors::EntityNotFoundException`
254
+ Job de Glue no existe. En `job_exists?` se rescata y retorna `false`. En `get_job`, `update_job` y `delete_job` se propaga.
255
+
256
+ ### `Aws::Glue::Errors::ServiceError`
257
+ Error genérico de AWS Glue. Se propaga en todos los métodos de lifecycle. Los métodos emiten `glue_runner.job_*_error` antes de propagar.
258
+
200
259
  ## Antipatrones
201
260
 
202
261
  Catálogo completo en [Antipatrones](references/antipatrones.md). Resumen de los más críticos:
@@ -207,10 +266,12 @@ Catálogo completo en [Antipatrones](references/antipatrones.md). Resumen de los
207
266
  4. **Validar `idle_in_transaction_session_timeout` con `.present?`** — `0.present?` es `false`, ignora la config.
208
267
  5. **Usar `<= end_of_day`** en rangos de fecha — pierde registros con microsegundos.
209
268
  6. **Loguear `source=`** manualmente — duplica el campo que inyecta `exis_ray`.
269
+ 7. **Usar nombres de Glue Job con guiones bajos al inicio** — `validate_glue_name!` rechaza `_my-job`. Usar `my-job` o `my_job` (sin underscore inicial).
210
270
 
211
271
  ## Referencias
212
272
 
213
273
  - [API Detallada](references/api-detallada.md) — Firmas completas, parámetros, retornos y comportamientos de cada clase pública.
274
+ - [Glue Jobs Lifecycle](https://github.com/gedera/data_drain/blob/main/docs/glue-jobs-lifecycle.md) — Guía completa de gestión de AWS Glue Jobs: crear, actualizar, eliminar, verificar y ejecutar jobs idempotentemente.
214
275
  - [Eventos y Telemetría](references/eventos-telemetria.md) — Catálogo completo de eventos KV emitidos por la gema.
215
276
  - [Antipatrones](references/antipatrones.md) — Qué NO hacer y alternativas correctas.
216
277
  - [Postgres Tuning](references/postgres-tuning.md) — Índices, VACUUM, particionamiento y diagnóstico por tamaño de tabla.
@@ -115,6 +115,15 @@ Catálogo completo de eventos KV emitidos por DataDrain. Formato Wispro-Observab
115
115
  **Nivel:** INFO. Emite antes de `start_job_run`.
116
116
  **Campos:** `job`.
117
117
 
118
+ ### `glue_runner.script_uploaded`
119
+ **Nivel:** INFO. Emite tras subir un script a S3 (v0.5.0+).
120
+ **Campos:** `local_path`, `s3_path`, `bytes`.
121
+
122
+ ### `glue_runner.script_upload_error`
123
+ **Nivel:** ERROR. Emite si el upload a S3 falla (v0.5.0+).
124
+ **Campos:** `local_path`, `bucket`, `error_class`, `error_message`.
125
+ **Consecuencia:** propaga el `Aws::S3::Errors::ServiceError`.
126
+
118
127
  ### `glue_runner.job_exists`
119
128
  **Nivel:** INFO. Emite en `ensure_job` cuando el job ya existe y se actualiza.
120
129
  **Campos:** `job`.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_drain
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel
@@ -104,6 +104,8 @@ files:
104
104
  - docs/execution/archive/v0.3.0.md
105
105
  - docs/execution/archive/v0.3.1-OBSERVACIONES.md
106
106
  - docs/execution/archive/v0.3.1.md
107
+ - docs/execution/archives/v0.5.0-OBSERVACIONES.md
108
+ - docs/execution/archives/v0.5.0.md
107
109
  - docs/execution/v0.2.2.md
108
110
  - docs/execution/v0.4.0-OBSERVACIONES.md
109
111
  - docs/execution/v0.4.0.md