data_drain 0.2.1 → 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48ceb077ad9f22d8550ef1e1974faf7ae77fc9fd2551b26343b067bb50ca36da
4
- data.tar.gz: 1fee979b853e79384be9f18b4031c4b5a5cb4a3519a3e95da1824d5546d60283
3
+ metadata.gz: ce021179463aeff31239f3bba35fc8b663633bfd648a2584a723b64b5d444387
4
+ data.tar.gz: b41a91f9a7792f952402c7ac2c9dc981e8372178df200c66e9d7fd8c63753c9c
5
5
  SHA512:
6
- metadata.gz: 216ed91eaed0d850f4c882a87a6f9c689ad4f934b60e005967a8236d8d68daecdbf3b7ccc066875e93bdb2ae371db375166fae238069e56d7936ff1a341eeb91
7
- data.tar.gz: 46595a513206b4966d58e4a42745ba1c86ba89f7cab21d3f1847446b87a1d32e8cdd5159a2dc6de58f5a579c9cc0446ed4fbc9c3702656d4309053451180d07e
6
+ metadata.gz: a23130f9892dfc34dfa748a50de6de5f768135d9b3bf012da0f648d322be6b11d0b20bbaf7e783d92a189cfc6e459cb7dc885800ea436f10d177f434e084e018
7
+ data.tar.gz: acbe4ed9caf168c7519881bce74c8ca90d8392bc8ee1f3718af600e64cfdacd3991f8860691db2b2ad9bb0c949aa88f0015f21e847f540030489951ba81f9ef0
data/CHANGELOG.md CHANGED
@@ -1,9 +1,31 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.2] - 2026-04-14
4
+
5
+ ### Security
6
+ - `Observability#safe_log` filtra secretos con regex `/password|passwd|pass|secret|token|api_key|apikey|auth|credential|private_key/i` — ahora captura variantes como `db_password`, `aws_secret_access_key`, `bearer_token`, `private_key`, `*credential*`. (item 9)
7
+
8
+ ### Features
9
+ - `GlueRunner.run_and_wait` acepta `max_wait_seconds:` para evitar bloqueo indefinido. Default `nil` (sin límite, backward-compatible). Emite `glue_runner.timeout` y levanta `DataDrain::Error` cuando excede. (item 7)
10
+ - `Configuration#validate!` y `Configuration#validate_for_engine!` invocados automáticamente en `Engine`, `FileIngestor` y `GlueRunner`. Falla rápido con errores descriptivos si falta configuración. (item 8)
11
+
12
+ ### Docs
13
+ - `skill/references/postgres-tuning.md`: guía de tuning Postgres por tamaño de tabla — índices, VACUUM post-purga, particionamiento, diagnóstico. (item 11a)
14
+
15
+ ### Cleanups (review PR #6)
16
+ - Fix typo `依赖` en CHANGELOG v0.2.1 (A1).
17
+ - Comment explicativo en `Record.disconnect!` rescue (A2).
18
+ - Cobertura real string-keys vs symbol-keys en `Record.build_query_path` (A3).
19
+ - Cerrar conn+db en `record_spec.rb#before(:all)` para evitar memory leak en suite (A4).
20
+ - Reorder `public`/`private` en `storage/s3.rb` (B1).
21
+
22
+ ### BREAKING (preventivo)
23
+ - `Engine.new` / `FileIngestor.new` / `GlueRunner.run_and_wait` ahora levantan `DataDrain::ConfigurationError` en el boot si la configuración está incompleta. Antes fallaban tarde con errores oscuros. La gema aún no está en uso en producción — no hay impacto real.
24
+
3
25
  ## [0.2.1] - 2026-04-13
4
26
 
5
27
  ### Correcciones
6
- - CI: Descarga binario pre-compilado de DuckDB en vez de依赖 del sistema (`libduckdb-dev`). Soporta Ruby 3.4.4 en GitHub Actions.
28
+ - CI: Descarga binario pre-compilado de DuckDB en vez de depender del sistema (`libduckdb-dev`). Soporta Ruby 3.4.4 en GitHub Actions.
7
29
  - CI: Opt-in a Node.js 24 (`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24`).
8
30
  - CI: Ejecuta solo specs en CI (RuboCop vía local) para evitar 48 ofensas pre-existentes en specs.
9
31
  - PR feedback: Test `aws_region` con comillas, `minimum_coverage` 80%, antipatrón 12 actualizado.
data/CLAUDE.md CHANGED
@@ -59,7 +59,7 @@ La telemetría debe ser estructurada (KV) para ser procesada por `exis_ray`.
59
59
  - **Automatización:** El campo `source` lo inyecta automáticamente `exis_ray` — no incluirlo manualmente.
60
60
  - **DEBUG:** Siempre en forma de bloque: `logger.debug { "k=#{v}" }`.
61
61
  - **Duraciones:** Usar siempre `Process.clock_gettime(Process::CLOCK_MONOTONIC)`.
62
- - **Sensibilidad:** Filtrar datos sensibles (`password`, `token`, `secret`) → `[FILTERED]`.
62
+ - **Sensibilidad:** `Observability#safe_log` filtra claves con regex `/password|passwd|pass|secret|token|api_key|apikey|auth|credential|private_key/i` → `[FILTERED]`.
63
63
 
64
64
  ## Código Ruby
65
65
 
@@ -79,3 +79,5 @@ bin/console # REPL de desarrollo
79
79
 
80
80
  - `limit_ram` y `tmp_directory` en la configuración evitan OOM en contenedores
81
81
  - DuckDB usa spill-to-disk automáticamente cuando `tmp_directory` está seteado
82
+ - Ver `skill/references/postgres-tuning.md` para guía de tuning por tamaño de tabla:
83
+ índices, VACUUM post-purga, y particionamiento declarativo para tablas >100GB
data/README.md CHANGED
@@ -51,6 +51,9 @@ DataDrain.configure do |config|
51
51
  config.limit_ram = '2GB' # evita OOM en contenedores
52
52
  config.tmp_directory = '/tmp/duckdb_work' # spill-to-disk (preferir SSD/NVMe)
53
53
 
54
+ # Tuning de Postgres: ver skill/references/postgres-tuning.md
55
+ # Índices para DELETE, VACUUM post-purga, particionamiento para tablas >100GB
56
+
54
57
  config.logger = Rails.logger
55
58
  end
56
59
  ```
@@ -1,7 +1,7 @@
1
1
  # DataDrain — Plan de Mejora v0.2.0 → v0.3.1
2
2
 
3
- **Versión actual:** 0.2.0
4
- **Última actualización:** 2026-04-13
3
+ **Versión actual:** 0.2.2
4
+ **Última actualización:** 2026-04-14
5
5
  **Owner:** Gabriel
6
6
  **Estado global:** No iniciado
7
7
 
@@ -32,7 +32,7 @@ DataDrain v0.1.19 es una gema bien arquitecturada (Storage Adapter, Observabilit
32
32
  - **Memory leak potencial:** conexión DuckDB thread-local sin cleanup.
33
33
  - **Documentación de tuning ausente:** sin guía para purgas masivas, índices, particionamiento.
34
34
 
35
- Este plan agrupa 17 items en 4 releases incrementales (v0.2.0 → v0.3.1) priorizados por impacto.
35
+ Este plan agrupa 24 items (17 originales + 7 surgidos post v0.2.1) en 5+ releases incrementales (v0.2.0 → v0.3.1) priorizados por impacto.
36
36
 
37
37
  ---
38
38
 
@@ -502,7 +502,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
502
502
 
503
503
  #### Item 7 — `max_wait_seconds` en `GlueRunner.run_and_wait`
504
504
 
505
- **Estado:** `[ ]`
505
+ **Estado:** `[x]`
506
506
  **Prioridad:** P1
507
507
  **Tipo:** `feat`
508
508
  **Compatibilidad:** backward-compatible
@@ -553,7 +553,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
553
553
 
554
554
  #### Item 8 — `Configuration#validate!`
555
555
 
556
- **Estado:** `[ ]`
556
+ **Estado:** `[x]`
557
557
  **Prioridad:** P1
558
558
  **Tipo:** `feat`
559
559
  **Compatibilidad:** backward-compatible (validación opcional explícita)
@@ -624,7 +624,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
624
624
 
625
625
  #### Item 9 — Filtro de secretos por regex en Observability
626
626
 
627
- **Estado:** `[ ]`
627
+ **Estado:** `[x]`
628
628
  **Prioridad:** P1
629
629
  **Tipo:** `security`
630
630
  **Compatibilidad:** backward-compatible (filtra más, no menos)
@@ -670,7 +670,7 @@ val = SENSITIVE_KEY_PATTERN.match?(k.to_s) ? "[FILTERED]" : v
670
670
 
671
671
  #### Item 11a — Documentación de Postgres tuning por tamaño de tabla
672
672
 
673
- **Estado:** `[ ]`
673
+ **Estado:** `[x]`
674
674
  **Prioridad:** P1
675
675
  **Tipo:** `docs`
676
676
  **Compatibilidad:** N/A
@@ -1091,6 +1091,261 @@ Solo donde sea limpio. No forzar.
1091
1091
 
1092
1092
  ---
1093
1093
 
1094
+ ### Items nuevos — surgidos post v0.2.1 (no en plan original)
1095
+
1096
+ Agregados el 2026-04-14 tras review de v0.2.1 y análisis del workaround de CI.
1097
+
1098
+ ---
1099
+
1100
+ #### Item 17 — Arreglar 48 ofensas RuboCop en `spec/` y re-habilitar en CI
1101
+
1102
+ **Estado:** `[ ]`
1103
+ **Prioridad:** P2
1104
+ **Tipo:** `chore` `test`
1105
+ **Compatibilidad:** N/A
1106
+ **Estimación:** M (3-5h)
1107
+ **Release sugerido:** v0.3.1
1108
+
1109
+ ##### Contexto
1110
+
1111
+ v0.2.1 excluyó `spec/` de RuboCop en `.rubocop.yml` para desbloquear el CI. La exclusión oculta ~48 ofensas preexistentes. El item 14 del roadmap ("CI con GitHub Actions") asume que RuboCop corre en CI — hoy no aplica a specs.
1112
+
1113
+ ##### Cambios
1114
+
1115
+ 1. Quitar `Exclude: - spec/` de `.rubocop.yml`.
1116
+ 2. `bundle exec rubocop spec/ --auto-correct` para fixes automáticos.
1117
+ 3. Fix manual de ofensas no auto-corregibles (típicamente `Metrics/BlockLength`, `RSpec/MultipleExpectations`, etc.).
1118
+ 4. Re-habilitar rubocop en el workflow CI (`.github/workflows/main.yml`).
1119
+
1120
+ ##### Criterios de aceptación
1121
+
1122
+ - [ ] `bundle exec rubocop` (sin argumentos, todo el proyecto) sin ofensas.
1123
+ - [ ] Workflow CI corre `bundle exec rubocop` antes de `rspec`.
1124
+ - [ ] Todos los specs siguen pasando después del auto-correct.
1125
+
1126
+ ##### Riesgos
1127
+
1128
+ - **Auto-correct puede romper tests.** Correr `rspec` tras cada batch de auto-correct.
1129
+ - Algunas ofensas requieren configurar `RSpec/*` cops con límites razonables (ej. `Max: 20` para `RSpec/ExampleLength`).
1130
+
1131
+ ---
1132
+
1133
+ #### Item 18 — Matrix Ruby en CI (3.2, 3.3, 3.4)
1134
+
1135
+ **Estado:** `[ ]`
1136
+ **Prioridad:** P2
1137
+ **Tipo:** `chore`
1138
+ **Compatibilidad:** N/A
1139
+ **Estimación:** S (1-2h)
1140
+ **Release sugerido:** v0.3.1
1141
+
1142
+ ##### Contexto
1143
+
1144
+ v0.2.1 solo corre CI en Ruby 3.4.4. La gema declara `required_ruby_version = ">= 3.0.0"`. Para validar compatibilidad con Rubies soportadas por Rails (3.2, 3.3), agregar matrix.
1145
+
1146
+ ##### Cambios
1147
+
1148
+ 1. En `.github/workflows/main.yml`:
1149
+ ```yaml
1150
+ strategy:
1151
+ matrix:
1152
+ ruby: ["3.2", "3.3", "3.4"]
1153
+ ```
1154
+ 2. Verificar que el binario pre-compilado de DuckDB 1.4.4 funciona en las 3 versiones de Ruby (debería — C ABI estable).
1155
+ 3. Ajustar `TargetRubyVersion` en `.rubocop.yml` si corresponde (hoy `3.2`, puede bajarse a `3.0` si la gema lo soporta realmente — verificar `required_ruby_version`).
1156
+
1157
+ ##### Criterios de aceptación
1158
+
1159
+ - [ ] Matrix con 3 versiones Ruby corre en CI.
1160
+ - [ ] Tiempo total < 10 min.
1161
+ - [ ] Las 3 versiones pasan specs.
1162
+
1163
+ ##### Riesgos
1164
+
1165
+ - **DuckDB prebuilt binary dep** — si la C extension no linkea bien en alguna versión, tendrá que recompilar (cambia tiempo de CI).
1166
+
1167
+ ---
1168
+
1169
+ #### Item 19 — Migrar tests S3 de `stub_const` a `Aws::S3::Client.stub_responses`
1170
+
1171
+ **Estado:** `[ ]`
1172
+ **Prioridad:** P2
1173
+ **Tipo:** `refactor` `test`
1174
+ **Compatibilidad:** N/A
1175
+ **Estimación:** S (2h)
1176
+ **Release sugerido:** v0.3.1
1177
+
1178
+ ##### Contexto
1179
+
1180
+ `spec/data_drain/storage/s3_spec.rb` usa `stub_const("Aws::S3::Client", Class.new ...)` para mockear el cliente AWS. Esto reemplaza la clase entera y es frágil (si AWS SDK agrega métodos nuevos, los tests no los cubren). AWS SDK soporta nativamente `Aws::S3::Client.new(stub_responses: true)`.
1181
+
1182
+ ##### Cambios
1183
+
1184
+ 1. En `spec/data_drain/storage/s3_spec.rb`, reemplazar `stub_const` por:
1185
+ ```ruby
1186
+ let(:s3_client) { Aws::S3::Client.new(stub_responses: true) }
1187
+
1188
+ before do
1189
+ s3_client.stub_responses(:list_objects_v2, contents: [...])
1190
+ allow(Aws::S3::Client).to receive(:new).and_return(s3_client)
1191
+ end
1192
+ ```
1193
+ 2. Los tests de `destroy_partitions` quedan más declarativos.
1194
+
1195
+ ##### Criterios de aceptación
1196
+
1197
+ - [ ] Tests pasan con el SDK real (`stub_responses` usa el client real, no mock).
1198
+ - [ ] No más `stub_const("Aws::S3::Client", ...)`.
1199
+ - [ ] Cobertura igual o superior.
1200
+
1201
+ ##### Riesgos
1202
+
1203
+ - **Setup diferente:** `stub_responses` requiere configurar cada API call. Más verboso pero más robusto.
1204
+
1205
+ ---
1206
+
1207
+ #### Item 20 — Limpiar `rubocop:disable` en `lib/` agregados en v0.2.0
1208
+
1209
+ **Estado:** `[ ]`
1210
+ **Prioridad:** P2
1211
+ **Tipo:** `refactor`
1212
+ **Compatibilidad:** N/A
1213
+ **Estimación:** Depende del item 10 (refactor Engine#call)
1214
+ **Release sugerido:** v0.3.0 (junto con item 10)
1215
+
1216
+ ##### Contexto
1217
+
1218
+ v0.2.0 agregó `# rubocop:disable` extensivos en 4 archivos:
1219
+ - `lib/data_drain/engine.rb`: `Metrics/ClassLength, AbcSize, MethodLength, Naming/AccessorMethodName`
1220
+ - `lib/data_drain/file_ingestor.rb`: `Metrics/AbcSize, CyclomaticComplexity, PerceivedComplexity, MethodLength`
1221
+ - `lib/data_drain/record.rb`: `Metrics/AbcSize, MethodLength`
1222
+ - `lib/data_drain/storage/s3.rb`: `Metrics/AbcSize, CyclomaticComplexity, MethodLength`
1223
+
1224
+ Workaround razonable durante v0.2.0 pero deja deuda visible.
1225
+
1226
+ ##### Cambios
1227
+
1228
+ Item 10 del roadmap (refactor `Engine#call` CC=13→5) resolverá parte. Este item complementa:
1229
+
1230
+ 1. Refactor `FileIngestor#call` en métodos privados (similar a item 10 para Engine).
1231
+ 2. Refactor `Storage::S3#setup_duckdb` + `#create_s3_secret` — el CC viene del branching credencial explícita vs `credential_chain`. Puede simplificarse.
1232
+ 3. Refactor `Record#execute_and_instantiate` — probablemente un guard clause resuelve.
1233
+ 4. Quitar todos los `rubocop:disable` a medida que se refactoriza.
1234
+
1235
+ ##### Criterios de aceptación
1236
+
1237
+ - [ ] Ningún `# rubocop:disable Metrics/*` en `lib/`.
1238
+ - [ ] `bundle exec rubocop lib/` sin ofensas ni disables.
1239
+ - [ ] Tests verdes.
1240
+
1241
+ ##### Riesgos
1242
+
1243
+ - **Refactor mayor de `FileIngestor`** — no tiene tests integration tan robustos como Engine. Requiere atención.
1244
+
1245
+ ---
1246
+
1247
+ #### Item 22 — Cache de RuboCop en CI
1248
+
1249
+ **Estado:** `[ ]`
1250
+ **Prioridad:** P3
1251
+ **Tipo:** `chore`
1252
+ **Compatibilidad:** N/A
1253
+ **Estimación:** XS (30min)
1254
+ **Release sugerido:** v0.3.1
1255
+ **Origen:** Review big-pickle 2026-04-14 (ClickUp 86b9dka0c).
1256
+
1257
+ ##### Contexto
1258
+
1259
+ Cuando el item 17 re-habilite rubocop en CI, correrá en cada push. Cachear el resultado con `actions/cache` sobre `~/.cache/rubocop_cache` acelera runs subsecuentes de 30s a <5s.
1260
+
1261
+ ##### Cambios
1262
+
1263
+ En `.github/workflows/main.yml`, agregar step antes de `rubocop`:
1264
+ ```yaml
1265
+ - uses: actions/cache@v4
1266
+ with:
1267
+ path: ~/.cache/rubocop_cache
1268
+ key: rubocop-${{ matrix.ruby }}-${{ hashFiles('.rubocop.yml') }}
1269
+ restore-keys: rubocop-${{ matrix.ruby }}-
1270
+ ```
1271
+
1272
+ ##### Criterios de aceptación
1273
+
1274
+ - [ ] Runs subsecuentes (sin cambios en `.rubocop.yml`) bajan tiempo de rubocop step.
1275
+ - [ ] Cache invalida correctamente si `.rubocop.yml` cambia.
1276
+
1277
+ ##### Riesgos
1278
+
1279
+ - Ninguno significativo.
1280
+
1281
+ ---
1282
+
1283
+ #### Item 23 — Coverage ≥ 90% en SimpleCov
1284
+
1285
+ **Estado:** `[ ]`
1286
+ **Prioridad:** P2
1287
+ **Tipo:** `test`
1288
+ **Compatibilidad:** N/A
1289
+ **Estimación:** M (4-6h)
1290
+ **Release sugerido:** v0.3.1
1291
+ **Origen:** Review big-pickle 2026-04-14.
1292
+
1293
+ ##### Contexto
1294
+
1295
+ v0.2.0 dejó `minimum_coverage 80` con cobertura real ~97%. Subir el umbral a 90% previene regresiones futuras y obliga a cubrir ramas nuevas.
1296
+
1297
+ ##### Cambios
1298
+
1299
+ 1. `spec/spec_helper.rb`: cambiar `minimum_coverage 80` → `minimum_coverage 90`.
1300
+ 2. Correr `bundle exec rspec` y verificar qué ramas quedan descubiertas.
1301
+ 3. Agregar tests para cubrirlas (típicamente branches de error, edge cases de `safe_log` y `destroy_partitions`).
1302
+
1303
+ ##### Criterios de aceptación
1304
+
1305
+ - [ ] `SimpleCov` reporta ≥ 90% líneas.
1306
+ - [ ] Ningún archivo de `lib/` con cobertura < 80%.
1307
+ - [ ] CI falla si alguna corrida baja del 90%.
1308
+
1309
+ ##### Riesgos
1310
+
1311
+ - Puede requerir tests con Postgres real para cubrir `purge_from_postgres` completo — decidir si entran en el suite default o bajo tag `:integration`.
1312
+
1313
+ ---
1314
+
1315
+ #### Item 24 — CI badge en README
1316
+
1317
+ **Estado:** `[ ]`
1318
+ **Prioridad:** P3
1319
+ **Tipo:** `docs`
1320
+ **Compatibilidad:** N/A
1321
+ **Estimación:** XS (10min)
1322
+ **Release sugerido:** v0.3.1
1323
+ **Origen:** Review big-pickle 2026-04-14.
1324
+
1325
+ ##### Contexto
1326
+
1327
+ README no muestra estado de CI. Un badge al inicio confirma visualmente que la gema es activamente testeada.
1328
+
1329
+ ##### Cambios
1330
+
1331
+ Agregar al tope del README después del título:
1332
+ ```markdown
1333
+ # DataDrain
1334
+
1335
+ [![CI](https://github.com/gedera/data_drain/actions/workflows/main.yml/badge.svg)](https://github.com/gedera/data_drain/actions/workflows/main.yml)
1336
+ ```
1337
+
1338
+ Opcionalmente badges adicionales:
1339
+ - Cobertura (requiere integrar con CodeClimate o Codecov)
1340
+ - Version de Gem (si se publica en RubyGems)
1341
+
1342
+ ##### Criterios de aceptación
1343
+
1344
+ - [ ] Badge se ve verde en main.
1345
+ - [ ] Badge apunta al workflow correcto.
1346
+
1347
+ ---
1348
+
1094
1349
  ## Riesgos transversales
1095
1350
 
1096
1351
  ### Coordinación con Gemini