89730911c2
Tracking de issues completados (jupyter tools) y funciones implementadas (specs de diseño ya resueltas).
3.8 KiB
3.8 KiB
Scheduling / Cron
Gap identificado en el registry. Reimplementar desde cero.
Los pipelines se lanzan manualmente o desde la TUI. No hay scheduling recurrente dentro del registry. Complementario a Dagu — estas funciones son primitivas componibles, no un scheduler completo.
Funciones a implementar
parse_cron_expr
- Dominio: core
- Lang: Go
- Purity: pure
- Signature:
ParseCronExpr(expr string) (CronSchedule, error) - Retorno: CronSchedule con campos Minute, Hour, DayOfMonth, Month, DayOfWeek parseados
- Descripcion: Parser de expresiones cron estandar (5 campos). Soporta
*, rangos (1-5), listas (1,3,5), pasos (*/15), y aliases (@hourly, @daily, @weekly, @monthly). No soporta seconds ni years (no es Quartz). - Algoritmo:
- Check aliases (@hourly → "0 * * * *", etc)
- Split por espacios, validar 5 campos
- Por campo: expandir
*a rango completo, parsear rangos/listas/pasos - Validar limites (minute 0-59, hour 0-23, etc)
- Deps:
strings,strconv,fmt(solo stdlib) - Tests:
- "*/15 * * * *" → minutos [0,15,30,45]
- "0 9 * * 1-5" → 9am weekdays
- "@daily" → "0 0 * * *"
- "0 9 1,15 * *" → dia 1 y 15 a las 9
- Expresion invalida → error descriptivo
- Campo fuera de rango → error
next_cron_time
- Dominio: core
- Lang: Go
- Purity: pure
- Signature:
NextCronTime(schedule CronSchedule, after time.Time) time.Time - Retorno: Proximo time.Time que cumple el schedule despues de
after - Descripcion: Calcula la proxima ejecucion de un cron schedule. Avanza minuto a minuto desde
afterhasta encontrar un match. Limit de 366 dias para evitar loops infinitos en schedules imposibles. - Algoritmo:
- Truncar
afteral minuto, avanzar 1 minuto - Check month → si no match, avanzar al primer dia del proximo mes valido
- Check day of month y day of week → si no match, avanzar al proximo dia
- Check hour → si no match, avanzar a la proxima hora
- Check minute → si no match, avanzar al proximo minuto
- Truncar
- Deps:
time - Tests:
- "0 * * * *" desde 14:30 → 15:00
- "0 9 * * 1" desde viernes → proximo lunes 9:00
- "0 0 29 2 *" → proximo 29 de febrero
- Schedule imposible → panic o error despues de limit
cron_ticker
- Dominio: infra
- Lang: Go
- Purity: impure (goroutine + channel + time)
- Signature:
CronTicker(schedule CronSchedule, ctx context.Context) <-chan time.Time - Retorno: Channel que emite un time.Time en cada tick del schedule
- Descripcion: Crea un ticker que emite en los momentos definidos por el cron schedule. Usa time.NewTimer internamente, recalculando el proximo tick despues de cada emision. Se detiene al cancelar el context.
- Deps:
time,context - Tests:
- Ticker con schedule "* * * * *" emite cada minuto (test con clock mock o schedule rapido)
- Context cancel detiene el ticker
- Channel se cierra al cancelar
parse_cron_expr (Python)
- Dominio: core
- Lang: Python
- Purity: pure
- Signature:
parse_cron_expr(expr: str) -> dict - Retorno:
{"minute": list[int], "hour": list[int], "day_of_month": list[int], "month": list[int], "day_of_week": list[int]} - Descripcion: Misma semantica que Go. Dict en vez de struct.
- Tests: Mismos casos que Go
next_cron_time (Python)
- Dominio: core
- Lang: Python
- Purity: pure
- Signature:
next_cron_time(schedule: dict, after: datetime) -> datetime - Descripcion: Misma semantica que Go.
- Tests: Mismos casos que Go
Tipo a implementar
CronSchedule (Go)
- Dominio: core
- Lang: Go
- Algebraic: product
- Definicion:
type CronSchedule struct { Minute []int Hour []int DayOfMonth []int Month []int DayOfWeek []int Raw string // expresion original }