data_drain 0.2.1 → 0.3.0
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 +4 -4
- data/CHANGELOG.md +46 -1
- data/CLAUDE.md +3 -1
- data/README.md +3 -0
- data/docs/IMPROVEMENT_PLAN.md +271 -11
- data/docs/execution/v0.2.2.md +891 -0
- data/lib/data_drain/configuration.rb +55 -5
- data/lib/data_drain/engine.rb +183 -72
- data/lib/data_drain/file_ingestor.rb +65 -47
- data/lib/data_drain/glue_runner.rb +22 -10
- data/lib/data_drain/observability/timing.rb +23 -0
- data/lib/data_drain/observability.rb +4 -2
- data/lib/data_drain/record.rb +10 -16
- data/lib/data_drain/storage/s3.rb +60 -45
- data/lib/data_drain/version.rb +1 -1
- data/lib/data_drain.rb +1 -0
- data/skill/SKILL.md +1 -0
- data/skill/references/antipatrones.md +20 -3
- data/skill/references/api-detallada.md +18 -5
- data/skill/references/eventos-telemetria.md +5 -0
- data/skill/references/postgres-tuning.md +129 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fc6bdf2a5a21825f9bc07185c0fc259056646c6084de2a42fd2d4e3198af4f2
|
|
4
|
+
data.tar.gz: aa7623b2ec910da4491c38904aa4623fd48a466ccc97a38124f29aafd9677655
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0201838e917434b529250689a5987008f9e8895366b56a78522752fe5b490fb6ab3d0b4c40dc81bcc830af3132c005fc8d136ab719093a16f0c9de5221e3421c'
|
|
7
|
+
data.tar.gz: 5be0c9c4a47d07f479f49c977d0490aad909a33fbc0c9292594bd51163132ee5229e0131f23d253120732d530930e5474bd31abbef7a5289f3022055799b5525
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,54 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-04-15
|
|
4
|
+
|
|
5
|
+
### Refactor
|
|
6
|
+
- `Engine#call` refactorizado: extraídos `step_count`, `step_export`, `step_verify`, `step_purge` como métodos privados con `timed` helper. CC bajó de 13 a 5. Eventos emitidos idénticos al comportamiento anterior. (item 10)
|
|
7
|
+
- Extraído `DataDrain::Observability::Timing` mixin compartido entre Engine y FileIngestor. (item 20)
|
|
8
|
+
- `FileIngestor#call` refactorizado análogo a Engine. (item 20)
|
|
9
|
+
- Eliminados todos los `# rubocop:disable Metrics/*` en `lib/`. (item 20)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
- `config.vacuum_after_purge = false` (default). Si `true`, ejecuta `VACUUM ANALYZE` post-purga cuando hubo deletes. Emite `engine.vacuum_complete` con dead_tuples antes/después y duración. Errores PG se capturan como `engine.vacuum_error` WARN. (item 5)
|
|
13
|
+
- `config.slow_batch_threshold_s = 30` y `config.slow_batch_alert_after = 5`. Detecta lotes de purga lentos. Emite `engine.slow_batch` WARN por cada lote lento, `engine.purge_degraded` WARN una vez por streak. Incluye hint a docs de tuning. (item 11b)
|
|
14
|
+
|
|
15
|
+
### Security
|
|
16
|
+
- `Record.connection` aplica `SET lock_configuration=true` post-setup. Congela cualquier SET futuro sobre la conexión (defensa en profundidad). NO afecta secrets ni extensiones ya cargadas. (item 6)
|
|
17
|
+
|
|
18
|
+
### Telemetry nueva
|
|
19
|
+
- `engine.vacuum_complete`, `engine.vacuum_error`, `engine.slow_batch`, `engine.purge_degraded`.
|
|
20
|
+
|
|
21
|
+
### Tests
|
|
22
|
+
- Coverage se mantiene ≥ 80%.
|
|
23
|
+
- Nuevo test de equivalencia para Engine (eventos idénticos pre/post refactor).
|
|
24
|
+
- Timecop agregado para tests de timing (item 11b).
|
|
25
|
+
|
|
26
|
+
## [0.2.2] - 2026-04-14
|
|
27
|
+
|
|
28
|
+
### Security
|
|
29
|
+
- `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)
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
- `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)
|
|
33
|
+
- `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)
|
|
34
|
+
|
|
35
|
+
### Docs
|
|
36
|
+
- `skill/references/postgres-tuning.md`: guía de tuning Postgres por tamaño de tabla — índices, VACUUM post-purga, particionamiento, diagnóstico. (item 11a)
|
|
37
|
+
|
|
38
|
+
### Cleanups (review PR #6)
|
|
39
|
+
- Fix typo `依赖` en CHANGELOG v0.2.1 (A1).
|
|
40
|
+
- Comment explicativo en `Record.disconnect!` rescue (A2).
|
|
41
|
+
- Cobertura real string-keys vs symbol-keys en `Record.build_query_path` (A3).
|
|
42
|
+
- Cerrar conn+db en `record_spec.rb#before(:all)` para evitar memory leak en suite (A4).
|
|
43
|
+
- Reorder `public`/`private` en `storage/s3.rb` (B1).
|
|
44
|
+
|
|
45
|
+
### BREAKING (preventivo)
|
|
46
|
+
- `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.
|
|
47
|
+
|
|
3
48
|
## [0.2.1] - 2026-04-13
|
|
4
49
|
|
|
5
50
|
### Correcciones
|
|
6
|
-
- CI: Descarga binario pre-compilado de DuckDB en vez de
|
|
51
|
+
- CI: Descarga binario pre-compilado de DuckDB en vez de depender del sistema (`libduckdb-dev`). Soporta Ruby 3.4.4 en GitHub Actions.
|
|
7
52
|
- CI: Opt-in a Node.js 24 (`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24`).
|
|
8
53
|
- CI: Ejecuta solo specs en CI (RuboCop vía local) para evitar 48 ofensas pre-existentes en specs.
|
|
9
54
|
- 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:**
|
|
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
|
```
|
data/docs/IMPROVEMENT_PLAN.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DataDrain — Plan de Mejora v0.2.0 → v0.3.1
|
|
2
2
|
|
|
3
|
-
**Versión actual:** 0.2.
|
|
4
|
-
**Última actualización:** 2026-04-
|
|
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
|
|
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
|
|
|
@@ -433,12 +433,13 @@ spec/
|
|
|
433
433
|
|
|
434
434
|
#### Item 5 — VACUUM ANALYZE opcional post-purga
|
|
435
435
|
|
|
436
|
-
**Estado:** `[
|
|
436
|
+
**Estado:** `[x]`
|
|
437
437
|
**Prioridad:** P1
|
|
438
438
|
**Tipo:** `feat` `perf`
|
|
439
439
|
**Compatibilidad:** backward-compatible (default `false`, opt-in)
|
|
440
440
|
**Estimación:** S (2-3h)
|
|
441
441
|
**Release:** v0.2.1
|
|
442
|
+
**Commit:** `93bf8a8`
|
|
442
443
|
|
|
443
444
|
##### Contexto
|
|
444
445
|
|
|
@@ -502,7 +503,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
|
|
|
502
503
|
|
|
503
504
|
#### Item 7 — `max_wait_seconds` en `GlueRunner.run_and_wait`
|
|
504
505
|
|
|
505
|
-
**Estado:** `[
|
|
506
|
+
**Estado:** `[x]`
|
|
506
507
|
**Prioridad:** P1
|
|
507
508
|
**Tipo:** `feat`
|
|
508
509
|
**Compatibilidad:** backward-compatible
|
|
@@ -553,7 +554,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
|
|
|
553
554
|
|
|
554
555
|
#### Item 8 — `Configuration#validate!`
|
|
555
556
|
|
|
556
|
-
**Estado:** `[
|
|
557
|
+
**Estado:** `[x]`
|
|
557
558
|
**Prioridad:** P1
|
|
558
559
|
**Tipo:** `feat`
|
|
559
560
|
**Compatibilidad:** backward-compatible (validación opcional explícita)
|
|
@@ -624,7 +625,7 @@ Purgar millones de rows deja dead tuples en Postgres. Sin `VACUUM`, el espacio n
|
|
|
624
625
|
|
|
625
626
|
#### Item 9 — Filtro de secretos por regex en Observability
|
|
626
627
|
|
|
627
|
-
**Estado:** `[
|
|
628
|
+
**Estado:** `[x]`
|
|
628
629
|
**Prioridad:** P1
|
|
629
630
|
**Tipo:** `security`
|
|
630
631
|
**Compatibilidad:** backward-compatible (filtra más, no menos)
|
|
@@ -670,7 +671,7 @@ val = SENSITIVE_KEY_PATTERN.match?(k.to_s) ? "[FILTERED]" : v
|
|
|
670
671
|
|
|
671
672
|
#### Item 11a — Documentación de Postgres tuning por tamaño de tabla
|
|
672
673
|
|
|
673
|
-
**Estado:** `[
|
|
674
|
+
**Estado:** `[x]`
|
|
674
675
|
**Prioridad:** P1
|
|
675
676
|
**Tipo:** `docs`
|
|
676
677
|
**Compatibilidad:** N/A
|
|
@@ -754,12 +755,13 @@ Contenido:
|
|
|
754
755
|
|
|
755
756
|
#### Item 6 — Sandboxing de `Record.connection`
|
|
756
757
|
|
|
757
|
-
**Estado:** `[
|
|
758
|
+
**Estado:** `[x]`
|
|
758
759
|
**Prioridad:** P1
|
|
759
760
|
**Tipo:** `security`
|
|
760
761
|
**Compatibilidad:** backward-compatible (con risk de breaking si caller hizo workarounds raros)
|
|
761
762
|
**Estimación:** M (3-4h)
|
|
762
763
|
**Release:** v0.3.0
|
|
764
|
+
**Commit:** `f042c56`
|
|
763
765
|
|
|
764
766
|
##### Contexto
|
|
765
767
|
|
|
@@ -800,12 +802,13 @@ Reduce blast radius si alguien intenta inyectar SQL malicioso vía `where_clause
|
|
|
800
802
|
|
|
801
803
|
#### Item 10 — Refactor `Engine#call` (CC=13 → ~5)
|
|
802
804
|
|
|
803
|
-
**Estado:** `[
|
|
805
|
+
**Estado:** `[x]`
|
|
804
806
|
**Prioridad:** P1
|
|
805
807
|
**Tipo:** `refactor`
|
|
806
808
|
**Compatibilidad:** backward-compatible
|
|
807
809
|
**Estimación:** M (4-6h)
|
|
808
810
|
**Release:** v0.3.0
|
|
811
|
+
**Commit:** `6a06850`
|
|
809
812
|
|
|
810
813
|
##### Contexto
|
|
811
814
|
|
|
@@ -878,12 +881,13 @@ Reduce blast radius si alguien intenta inyectar SQL malicioso vía `where_clause
|
|
|
878
881
|
|
|
879
882
|
#### Item 11b — Warning runtime de purga lenta sin avance
|
|
880
883
|
|
|
881
|
-
**Estado:** `[
|
|
884
|
+
**Estado:** `[x]`
|
|
882
885
|
**Prioridad:** P1
|
|
883
886
|
**Tipo:** `feat` `perf`
|
|
884
887
|
**Compatibilidad:** backward-compatible
|
|
885
888
|
**Estimación:** M (3-4h)
|
|
886
889
|
**Release:** v0.3.0
|
|
890
|
+
**Commit:** `d72ec0a`
|
|
887
891
|
|
|
888
892
|
##### Contexto
|
|
889
893
|
|
|
@@ -1091,6 +1095,262 @@ Solo donde sea limpio. No forzar.
|
|
|
1091
1095
|
|
|
1092
1096
|
---
|
|
1093
1097
|
|
|
1098
|
+
### Items nuevos — surgidos post v0.2.1 (no en plan original)
|
|
1099
|
+
|
|
1100
|
+
Agregados el 2026-04-14 tras review de v0.2.1 y análisis del workaround de CI.
|
|
1101
|
+
|
|
1102
|
+
---
|
|
1103
|
+
|
|
1104
|
+
#### Item 17 — Arreglar 48 ofensas RuboCop en `spec/` y re-habilitar en CI
|
|
1105
|
+
|
|
1106
|
+
**Estado:** `[ ]`
|
|
1107
|
+
**Prioridad:** P2
|
|
1108
|
+
**Tipo:** `chore` `test`
|
|
1109
|
+
**Compatibilidad:** N/A
|
|
1110
|
+
**Estimación:** M (3-5h)
|
|
1111
|
+
**Release sugerido:** v0.3.1
|
|
1112
|
+
|
|
1113
|
+
##### Contexto
|
|
1114
|
+
|
|
1115
|
+
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.
|
|
1116
|
+
|
|
1117
|
+
##### Cambios
|
|
1118
|
+
|
|
1119
|
+
1. Quitar `Exclude: - spec/` de `.rubocop.yml`.
|
|
1120
|
+
2. `bundle exec rubocop spec/ --auto-correct` para fixes automáticos.
|
|
1121
|
+
3. Fix manual de ofensas no auto-corregibles (típicamente `Metrics/BlockLength`, `RSpec/MultipleExpectations`, etc.).
|
|
1122
|
+
4. Re-habilitar rubocop en el workflow CI (`.github/workflows/main.yml`).
|
|
1123
|
+
|
|
1124
|
+
##### Criterios de aceptación
|
|
1125
|
+
|
|
1126
|
+
- [ ] `bundle exec rubocop` (sin argumentos, todo el proyecto) sin ofensas.
|
|
1127
|
+
- [ ] Workflow CI corre `bundle exec rubocop` antes de `rspec`.
|
|
1128
|
+
- [ ] Todos los specs siguen pasando después del auto-correct.
|
|
1129
|
+
|
|
1130
|
+
##### Riesgos
|
|
1131
|
+
|
|
1132
|
+
- **Auto-correct puede romper tests.** Correr `rspec` tras cada batch de auto-correct.
|
|
1133
|
+
- Algunas ofensas requieren configurar `RSpec/*` cops con límites razonables (ej. `Max: 20` para `RSpec/ExampleLength`).
|
|
1134
|
+
|
|
1135
|
+
---
|
|
1136
|
+
|
|
1137
|
+
#### Item 18 — Matrix Ruby en CI (3.2, 3.3, 3.4)
|
|
1138
|
+
|
|
1139
|
+
**Estado:** `[ ]`
|
|
1140
|
+
**Prioridad:** P2
|
|
1141
|
+
**Tipo:** `chore`
|
|
1142
|
+
**Compatibilidad:** N/A
|
|
1143
|
+
**Estimación:** S (1-2h)
|
|
1144
|
+
**Release sugerido:** v0.3.1
|
|
1145
|
+
|
|
1146
|
+
##### Contexto
|
|
1147
|
+
|
|
1148
|
+
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.
|
|
1149
|
+
|
|
1150
|
+
##### Cambios
|
|
1151
|
+
|
|
1152
|
+
1. En `.github/workflows/main.yml`:
|
|
1153
|
+
```yaml
|
|
1154
|
+
strategy:
|
|
1155
|
+
matrix:
|
|
1156
|
+
ruby: ["3.2", "3.3", "3.4"]
|
|
1157
|
+
```
|
|
1158
|
+
2. Verificar que el binario pre-compilado de DuckDB 1.4.4 funciona en las 3 versiones de Ruby (debería — C ABI estable).
|
|
1159
|
+
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`).
|
|
1160
|
+
|
|
1161
|
+
##### Criterios de aceptación
|
|
1162
|
+
|
|
1163
|
+
- [ ] Matrix con 3 versiones Ruby corre en CI.
|
|
1164
|
+
- [ ] Tiempo total < 10 min.
|
|
1165
|
+
- [ ] Las 3 versiones pasan specs.
|
|
1166
|
+
|
|
1167
|
+
##### Riesgos
|
|
1168
|
+
|
|
1169
|
+
- **DuckDB prebuilt binary dep** — si la C extension no linkea bien en alguna versión, tendrá que recompilar (cambia tiempo de CI).
|
|
1170
|
+
|
|
1171
|
+
---
|
|
1172
|
+
|
|
1173
|
+
#### Item 19 — Migrar tests S3 de `stub_const` a `Aws::S3::Client.stub_responses`
|
|
1174
|
+
|
|
1175
|
+
**Estado:** `[ ]`
|
|
1176
|
+
**Prioridad:** P2
|
|
1177
|
+
**Tipo:** `refactor` `test`
|
|
1178
|
+
**Compatibilidad:** N/A
|
|
1179
|
+
**Estimación:** S (2h)
|
|
1180
|
+
**Release sugerido:** v0.3.1
|
|
1181
|
+
|
|
1182
|
+
##### Contexto
|
|
1183
|
+
|
|
1184
|
+
`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)`.
|
|
1185
|
+
|
|
1186
|
+
##### Cambios
|
|
1187
|
+
|
|
1188
|
+
1. En `spec/data_drain/storage/s3_spec.rb`, reemplazar `stub_const` por:
|
|
1189
|
+
```ruby
|
|
1190
|
+
let(:s3_client) { Aws::S3::Client.new(stub_responses: true) }
|
|
1191
|
+
|
|
1192
|
+
before do
|
|
1193
|
+
s3_client.stub_responses(:list_objects_v2, contents: [...])
|
|
1194
|
+
allow(Aws::S3::Client).to receive(:new).and_return(s3_client)
|
|
1195
|
+
end
|
|
1196
|
+
```
|
|
1197
|
+
2. Los tests de `destroy_partitions` quedan más declarativos.
|
|
1198
|
+
|
|
1199
|
+
##### Criterios de aceptación
|
|
1200
|
+
|
|
1201
|
+
- [ ] Tests pasan con el SDK real (`stub_responses` usa el client real, no mock).
|
|
1202
|
+
- [ ] No más `stub_const("Aws::S3::Client", ...)`.
|
|
1203
|
+
- [ ] Cobertura igual o superior.
|
|
1204
|
+
|
|
1205
|
+
##### Riesgos
|
|
1206
|
+
|
|
1207
|
+
- **Setup diferente:** `stub_responses` requiere configurar cada API call. Más verboso pero más robusto.
|
|
1208
|
+
|
|
1209
|
+
---
|
|
1210
|
+
|
|
1211
|
+
#### Item 20 — Limpiar `rubocop:disable` en `lib/` agregados en v0.2.0
|
|
1212
|
+
|
|
1213
|
+
**Estado:** `[x]`
|
|
1214
|
+
**Prioridad:** P2
|
|
1215
|
+
**Tipo:** `refactor`
|
|
1216
|
+
**Compatibilidad:** N/A
|
|
1217
|
+
**Estimación:** Depende del item 10 (refactor Engine#call)
|
|
1218
|
+
**Release sugerido:** v0.3.0 (junto con item 10)
|
|
1219
|
+
**Commit:** `f6f4ddc` (FileIngestor), `02d207c` (S3 refactor), `5522c79` (Timing mixin)
|
|
1220
|
+
|
|
1221
|
+
##### Contexto
|
|
1222
|
+
|
|
1223
|
+
v0.2.0 agregó `# rubocop:disable` extensivos en 4 archivos:
|
|
1224
|
+
- `lib/data_drain/engine.rb`: `Metrics/ClassLength, AbcSize, MethodLength, Naming/AccessorMethodName`
|
|
1225
|
+
- `lib/data_drain/file_ingestor.rb`: `Metrics/AbcSize, CyclomaticComplexity, PerceivedComplexity, MethodLength`
|
|
1226
|
+
- `lib/data_drain/record.rb`: `Metrics/AbcSize, MethodLength`
|
|
1227
|
+
- `lib/data_drain/storage/s3.rb`: `Metrics/AbcSize, CyclomaticComplexity, MethodLength`
|
|
1228
|
+
|
|
1229
|
+
Workaround razonable durante v0.2.0 pero deja deuda visible.
|
|
1230
|
+
|
|
1231
|
+
##### Cambios
|
|
1232
|
+
|
|
1233
|
+
Item 10 del roadmap (refactor `Engine#call` CC=13→5) resolverá parte. Este item complementa:
|
|
1234
|
+
|
|
1235
|
+
1. Refactor `FileIngestor#call` en métodos privados (similar a item 10 para Engine).
|
|
1236
|
+
2. Refactor `Storage::S3#setup_duckdb` + `#create_s3_secret` — el CC viene del branching credencial explícita vs `credential_chain`. Puede simplificarse.
|
|
1237
|
+
3. Refactor `Record#execute_and_instantiate` — probablemente un guard clause resuelve.
|
|
1238
|
+
4. Quitar todos los `rubocop:disable` a medida que se refactoriza.
|
|
1239
|
+
|
|
1240
|
+
##### Criterios de aceptación
|
|
1241
|
+
|
|
1242
|
+
- [ ] Ningún `# rubocop:disable Metrics/*` en `lib/`.
|
|
1243
|
+
- [ ] `bundle exec rubocop lib/` sin ofensas ni disables.
|
|
1244
|
+
- [ ] Tests verdes.
|
|
1245
|
+
|
|
1246
|
+
##### Riesgos
|
|
1247
|
+
|
|
1248
|
+
- **Refactor mayor de `FileIngestor`** — no tiene tests integration tan robustos como Engine. Requiere atención.
|
|
1249
|
+
|
|
1250
|
+
---
|
|
1251
|
+
|
|
1252
|
+
#### Item 22 — Cache de RuboCop en CI
|
|
1253
|
+
|
|
1254
|
+
**Estado:** `[ ]`
|
|
1255
|
+
**Prioridad:** P3
|
|
1256
|
+
**Tipo:** `chore`
|
|
1257
|
+
**Compatibilidad:** N/A
|
|
1258
|
+
**Estimación:** XS (30min)
|
|
1259
|
+
**Release sugerido:** v0.3.1
|
|
1260
|
+
**Origen:** Review big-pickle 2026-04-14 (ClickUp 86b9dka0c).
|
|
1261
|
+
|
|
1262
|
+
##### Contexto
|
|
1263
|
+
|
|
1264
|
+
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.
|
|
1265
|
+
|
|
1266
|
+
##### Cambios
|
|
1267
|
+
|
|
1268
|
+
En `.github/workflows/main.yml`, agregar step antes de `rubocop`:
|
|
1269
|
+
```yaml
|
|
1270
|
+
- uses: actions/cache@v4
|
|
1271
|
+
with:
|
|
1272
|
+
path: ~/.cache/rubocop_cache
|
|
1273
|
+
key: rubocop-${{ matrix.ruby }}-${{ hashFiles('.rubocop.yml') }}
|
|
1274
|
+
restore-keys: rubocop-${{ matrix.ruby }}-
|
|
1275
|
+
```
|
|
1276
|
+
|
|
1277
|
+
##### Criterios de aceptación
|
|
1278
|
+
|
|
1279
|
+
- [ ] Runs subsecuentes (sin cambios en `.rubocop.yml`) bajan tiempo de rubocop step.
|
|
1280
|
+
- [ ] Cache invalida correctamente si `.rubocop.yml` cambia.
|
|
1281
|
+
|
|
1282
|
+
##### Riesgos
|
|
1283
|
+
|
|
1284
|
+
- Ninguno significativo.
|
|
1285
|
+
|
|
1286
|
+
---
|
|
1287
|
+
|
|
1288
|
+
#### Item 23 — Coverage ≥ 90% en SimpleCov
|
|
1289
|
+
|
|
1290
|
+
**Estado:** `[ ]`
|
|
1291
|
+
**Prioridad:** P2
|
|
1292
|
+
**Tipo:** `test`
|
|
1293
|
+
**Compatibilidad:** N/A
|
|
1294
|
+
**Estimación:** M (4-6h)
|
|
1295
|
+
**Release sugerido:** v0.3.1
|
|
1296
|
+
**Origen:** Review big-pickle 2026-04-14.
|
|
1297
|
+
|
|
1298
|
+
##### Contexto
|
|
1299
|
+
|
|
1300
|
+
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.
|
|
1301
|
+
|
|
1302
|
+
##### Cambios
|
|
1303
|
+
|
|
1304
|
+
1. `spec/spec_helper.rb`: cambiar `minimum_coverage 80` → `minimum_coverage 90`.
|
|
1305
|
+
2. Correr `bundle exec rspec` y verificar qué ramas quedan descubiertas.
|
|
1306
|
+
3. Agregar tests para cubrirlas (típicamente branches de error, edge cases de `safe_log` y `destroy_partitions`).
|
|
1307
|
+
|
|
1308
|
+
##### Criterios de aceptación
|
|
1309
|
+
|
|
1310
|
+
- [ ] `SimpleCov` reporta ≥ 90% líneas.
|
|
1311
|
+
- [ ] Ningún archivo de `lib/` con cobertura < 80%.
|
|
1312
|
+
- [ ] CI falla si alguna corrida baja del 90%.
|
|
1313
|
+
|
|
1314
|
+
##### Riesgos
|
|
1315
|
+
|
|
1316
|
+
- Puede requerir tests con Postgres real para cubrir `purge_from_postgres` completo — decidir si entran en el suite default o bajo tag `:integration`.
|
|
1317
|
+
|
|
1318
|
+
---
|
|
1319
|
+
|
|
1320
|
+
#### Item 24 — CI badge en README
|
|
1321
|
+
|
|
1322
|
+
**Estado:** `[ ]`
|
|
1323
|
+
**Prioridad:** P3
|
|
1324
|
+
**Tipo:** `docs`
|
|
1325
|
+
**Compatibilidad:** N/A
|
|
1326
|
+
**Estimación:** XS (10min)
|
|
1327
|
+
**Release sugerido:** v0.3.1
|
|
1328
|
+
**Origen:** Review big-pickle 2026-04-14.
|
|
1329
|
+
|
|
1330
|
+
##### Contexto
|
|
1331
|
+
|
|
1332
|
+
README no muestra estado de CI. Un badge al inicio confirma visualmente que la gema es activamente testeada.
|
|
1333
|
+
|
|
1334
|
+
##### Cambios
|
|
1335
|
+
|
|
1336
|
+
Agregar al tope del README después del título:
|
|
1337
|
+
```markdown
|
|
1338
|
+
# DataDrain
|
|
1339
|
+
|
|
1340
|
+
[](https://github.com/gedera/data_drain/actions/workflows/main.yml)
|
|
1341
|
+
```
|
|
1342
|
+
|
|
1343
|
+
Opcionalmente badges adicionales:
|
|
1344
|
+
- Cobertura (requiere integrar con CodeClimate o Codecov)
|
|
1345
|
+
- Version de Gem (si se publica en RubyGems)
|
|
1346
|
+
|
|
1347
|
+
##### Criterios de aceptación
|
|
1348
|
+
|
|
1349
|
+
- [ ] Badge se ve verde en main.
|
|
1350
|
+
- [ ] Badge apunta al workflow correcto.
|
|
1351
|
+
|
|
1352
|
+
---
|
|
1353
|
+
|
|
1094
1354
|
## Riesgos transversales
|
|
1095
1355
|
|
|
1096
1356
|
### Coordinación con Gemini
|