data_drain 0.4.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/docs/execution/v0.5.0-OBSERVACIONES.md +167 -0
- data/docs/execution/v0.5.0.md +900 -0
- data/docs/glue-jobs-lifecycle.md +184 -13
- data/docs/glue_pyspark_example.py +49 -19
- data/lib/data_drain/glue_runner.rb +153 -17
- data/lib/data_drain/storage/base.rb +12 -0
- data/lib/data_drain/storage/local.rb +13 -0
- data/lib/data_drain/storage/s3.rb +17 -0
- data/lib/data_drain/validations.rb +2 -2
- data/lib/data_drain/version.rb +1 -1
- data/skill/SKILL.md +64 -3
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c92c85e6232344565dc090539d3d58aa47904ca1e454b696ba4eba12e2648881
|
|
4
|
+
data.tar.gz: 1b3332ac50288dfd6793aed0c51ab8fa49d8dc309f7bc8dd4a642ecffd97e3cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d0cecb3d168ad96943b9cc70eb936e9b95e92d03dc0bd08ed5996ac1967ef627191802892097abf3b094d5b59515c150ca8edc4ffcefe13be8b4a2d7721a180a
|
|
7
|
+
data.tar.gz: 45018ca7e4287bf055cb7060e5720f83da318bd7c9ad44a30d8e832972feb1eb99d29286a9813128d4f84171d4c032e12f9a4f4dd7cc0022b36e44a3098d91c8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.5.0] - 2026-04-15
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- `Storage::S3#upload_file` y `Storage::Local#upload_file`: primitiva para subir archivos al storage configurado. (item 37)
|
|
8
|
+
- `GlueRunner.upload_script(local_path:, bucket:, folder:, filename:)`: sube script Python local a S3 usando el `Storage::S3` adapter existente. Emite `glue_runner.script_uploaded` (INFO) y `glue_runner.script_upload_error` (ERROR). (item 37)
|
|
9
|
+
- `GlueRunner.create_job` y `GlueRunner.ensure_job` aceptan `script_path:` + `script_bucket:` + `script_folder:` + `script_filename:` para subir scripts locales automáticamente. Si se usa `script_location:`, comportamiento idéntico al anterior. (item 37)
|
|
10
|
+
|
|
11
|
+
### Docs
|
|
12
|
+
|
|
13
|
+
- `docs/glue-jobs-lifecycle.md`: sección "Subir scripts locales" con patrón completo, permisos IAM mínimos y limitación de concurrencia.
|
|
14
|
+
- `docs/glue_pyspark_example.py`: ejemplo de uso con `script_path`.
|
|
15
|
+
|
|
16
|
+
### Notas
|
|
17
|
+
|
|
18
|
+
- **Upload NO es idempotente en sentido estricto:** `put_object` sobrescribe siempre. Documentado.
|
|
19
|
+
- `upload_script` requiere `storage_mode = :s3`. En `:local` levanta `ConfigurationError`.
|
|
20
|
+
|
|
3
21
|
## [0.4.0] - 2026-04-15
|
|
4
22
|
|
|
5
23
|
### Features
|
|
@@ -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
|