data_drain 0.3.2 → 0.5.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.
@@ -0,0 +1,167 @@
1
+ # Observaciones — v0.5.0
2
+
3
+ Generado por: big-pickle
4
+ Fecha: 2026-04-15
5
+ Revisor: big-pickle (análisis de código real vs plan v2)
6
+
7
+ ---
8
+
9
+ ## Observación 1 — Breaking change implícito en `create_job`/`ensure_job`
10
+
11
+ **Severidad:** Alta
12
+
13
+ **Hallazgo:** El plan dice "Breaking: ninguno", pero la firma cambia:
14
+
15
+ ```ruby
16
+ # ACTUAL (script_location: es keyword REQUIRED)
17
+ def self.create_job(job_name, role_arn:, script_location:, ...)
18
+
19
+ # PLAN (script_location: nil con default, role_arn: sigue required → SyntaxError)
20
+ def self.create_job(job_name, role_arn:, script_location: nil, script_path: nil, ...)
21
+ # required keyword argument cannot have a default value
22
+ ```
23
+
24
+ **Fix requerido:** `role_arn:` también debe tener default `nil`. Esto es técnicamente un cambio de API (aunque todos los callers usan kwargs, así que no rompe en la práctica).
25
+
26
+ **Estado:** Verificar en pre-flight checklist.
27
+
28
+ ---
29
+
30
+ ## Observación 2 — `s3_client` existe y usa credential chain
31
+
32
+ **Severidad:** Confirmada OK
33
+
34
+ **Verificado en** `lib/data_drain/storage/s3.rb:44-50`:
35
+
36
+ ```ruby
37
+ def s3_client
38
+ Aws::S3::Client.new(
39
+ region: @config.aws_region,
40
+ access_key_id: @config.aws_access_key_id,
41
+ secret_access_key: @config.aws_secret_access_key
42
+ )
43
+ end
44
+ ```
45
+
46
+ El SDK acepta `nil` en las credenciales y resuelve via credential chain automáticamente. Plan OK.
47
+
48
+ ---
49
+
50
+ ## Observación 3 — `changed_fields` incluye comparación de `script_location`
51
+
52
+ **Severidad:** Confirmada OK
53
+
54
+ **Verificado en** `lib/data_drain/glue_runner.rb:174-175`:
55
+
56
+ ```ruby
57
+ changed << :command if current.command.name != desired[:command_name] ||
58
+ current.command.script_location != desired[:script_location]
59
+ ```
60
+
61
+ El `script_location` se compara dentro de `:command`. Cuando `ensure_job` construya `desired[:script_location] = final_script` (resultado del upload), el diffing funcionará correctamente.
62
+
63
+ ---
64
+
65
+ ## Observación 4 — `Storage::Local#upload_file` requiere directorio manual
66
+
67
+ **Severidad:** Media
68
+
69
+ **Hallazgo:** No existe `Configuration#local_bucket`. El `bucket` en `Storage::Local#upload_file` es un directorio local pasado por el caller.
70
+
71
+ **Plan OK:** el plan ya documenta esto en la firma del método. Confirmar en pre-flight checklist que el implementador lo sepa.
72
+
73
+ ---
74
+
75
+ ## Observación 5 — `resolve_script_location` es `private_class_method` pero llamado desde métodos públicos
76
+
77
+ **Severidad:** Info
78
+
79
+ **Hallazgo:** Ruby permite que métodos públicos de clase llamen `private_class_method`. No hay error. El plan está correcto. Solo documentar para claridad del implementador.
80
+
81
+ ---
82
+
83
+ ## Observación 6 — `spec/data_drain/storage/local_spec.rb` no existe
84
+
85
+ **Severidad:** Media
86
+
87
+ **Hallazgo:** El plan propone specs para `Storage::Local#upload_file` pero el archivo no existe. Hay que crearlo en la fase correspondiente.
88
+
89
+ **Acción:** Crear `spec/data_drain/storage/local_spec.rb` con los specs del plan.
90
+
91
+ ---
92
+
93
+ ## Observación 7 — `spec/data_drain/glue_runner_spec.rb` tiene specs existentes de `create_job`/`ensure_job`
94
+
95
+ **Severidad:** Info
96
+
97
+ **Hallazgo:** Ya existen specs en `spec/data_drain/glue_runner_spec.rb:161+` para `create_job` y `ensure_job`. Los specs nuevos del plan deben ser adicionales a los existentes, no reemplazarlos. Verificar que los tests existentes sigan pasando.
98
+
99
+ ---
100
+
101
+ ## Observación 8 — Test de `storage_mode = :local` requiere `reset_adapter!`
102
+
103
+ **Severidad:** Baja
104
+
105
+ **Hallazgo:** El test "levanta ConfigurationError si storage_mode es :local" cambia `storage_mode` globalmente. Debe hacer `reset_adapter!` en el `after` block para no contaminar otros tests.
106
+
107
+ **Plan OK:** el plan menciona esto, solo confirmar que se implemente correctamente.
108
+
109
+ ---
110
+
111
+ ## Observación 9 — Campo `bytes` en evento observabilidad
112
+
113
+ **Severidad:** Baja
114
+
115
+ **Hallazgo:** El plan usa `bytes` como nombre de campo en `glue_runner.script_uploaded`. Según Wispro-Observability-Spec v1, los contadores deben usar la palabra `count` en la key.
116
+
117
+ **Alternativas:**
118
+ - `byte_count` (más consistente con spec)
119
+ - `file_size` (más semántico)
120
+
121
+ **Decisión:** Mantener `bytes` por convención established en contexto AWS/S3 (donde `ContentLength` se reporta como `bytes`). Bajo riesgo.
122
+
123
+ ---
124
+
125
+ ## Observación 10 — `content_type: "text/x-python"` es explícito
126
+
127
+ **Severidad:** Info
128
+
129
+ **Verificado:** S3 infiere correctamente `text/x-python` para archivos `.py` si no se provee. El plan usa explícito para mayor predictibilidad. OK.
130
+
131
+ ---
132
+
133
+ ## Observación 11 — Concurrencia sin lock
134
+
135
+ **Severidad:** Info
136
+
137
+ **Documentado en** plan. `put_object` sobrescribe siempre. Scripts PySpark son pequeños, riesgo bajo. Items 38 y 39 definidos como follow-ups.
138
+
139
+ ---
140
+
141
+ ## Resumen para el implementador
142
+
143
+ | # | Severidad | Acción |
144
+ |---|-----------|--------|
145
+ | 1 | Alta | Clarificar en plan que `role_arn:` también tiene default `nil` |
146
+ | 2 | Confirmada OK | `s3_client` existe, credential chain OK |
147
+ | 3 | Confirmada OK | `changed_fields` compara `script_location` |
148
+ | 4 | Media | Documentar que Local requiere directorio destino manual |
149
+ | 5 | Info | `private_class_method` permitido en Ruby de clase pública |
150
+ | 6 | Media | Crear `spec/data_drain/storage/local_spec.rb` |
151
+ | 7 | Info | Tests existentes de `create_job`/`ensure_job` no se tocan |
152
+ | 8 | Baja | Test de `storage_mode = :local` con `reset_adapter!` |
153
+ | 9 | Baja | Mantener `bytes` (convención AWS) |
154
+ | 10 | Info | `content_type` explícito OK |
155
+ | 11 | Info | Concurrencia documentada, items 38/39 follow-ups |
156
+
157
+ ---
158
+
159
+ ## Checklist de pre-implementación
160
+
161
+ - [ ] Clarificar que `role_arn:` también tiene default `nil` en el plan
162
+ - [ ] Verificar `s3_client` existe en `Storage::S3` ✅
163
+ - [ ] Verificar `changed_fields` incluye `script_location` ✅
164
+ - [ ] Confirmar que no hay `Configuration#local_bucket` existente
165
+ - [ ] Crear `spec/data_drain/storage/local_spec.rb`
166
+ - [ ] Ejecutar `bundle exec rspec` antes de empezar para tener baseline verde
167
+ - [ ] Ejecutar `bundle exec rubocop` antes de empezar para tener baseline verde