Files
egutierrez a03675113a chore: auto-commit (286 archivos)
- .claude/agents/fn-orquestador/SKILL.md
- .claude/commands/fn_claude.md
- .claude/rules/INDEX.md
- .claude/rules/cpp_apps.md
- .claude/rules/ids_naming.md
- CHANGELOG.md
- apps/dag_engine/README.md
- apps/dag_engine/api.go
- apps/dag_engine/dags_migrated/example.yaml
- apps/dag_engine/dags_migrated/example_lineage_tracking.yaml
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 16:33:22 +02:00

3.8 KiB

Scheduler — Cron expression parsing, matching, scheduling

Tag: scheduler. Grupo de funciones para trabajar con expresiones cron: parsear, validar coincidencias, calcular proximo run, traducir a lenguaje humano. Lo consume apps/dag_engine + cpp/apps/dag_engine_ui (tab Schedule). Crece a medida que se anaden nuevos formatos (Quartz, k8s CronJob, etc.).

Filtro MCP: mcp__registry__fn_search query="" tag="scheduler".

Funciones del grupo

ID Firma corta Que hace
parse_cron_expr_go_core ParseCronExpr(expr string) (CronSchedule, error) Parsea expresion cron de 5 campos a struct expandido. Soporta *, rangos, listas, pasos y aliases @hourly/@daily/@weekly/@monthly/@yearly.
cron_match_go_core CronMatch(s CronSchedule, t time.Time) bool True si un instante coincide con un schedule. Compara los 5 campos.
next_cron_time_go_core NextCronTime(s CronSchedule, after time.Time) time.Time Proxima ejecucion despues de un instante. Salta minuto a minuto. Zero time si no hay match en 366 dias.
cron_explain_go_core CronExplain(expr string) string Traduce expresion cron a frase humana corta ("every 15 minutes", "daily at 09:00", "weekdays at HH:MM").

Ejemplo canonico end-to-end

Trabajar con un schedule completo: parsear, calcular proximo run, explicarlo al usuario.

package main

import (
    "fmt"
    "time"
    "fn-registry/functions/core"
)

func main() {
    expr := "*/15 * * * *"

    // 1. Parsear
    sched, err := core.ParseCronExpr(expr)
    if err != nil {
        panic(err)
    }

    // 2. Proximo run
    next := core.NextCronTime(sched, time.Now())
    fmt.Printf("next run: %s\n", next.Format(time.RFC3339))

    // 3. Explicacion humana
    fmt.Printf("schedule: %s (%s)\n", expr, core.CronExplain(expr))
    // -> schedule: */15 * * * * (every 15 minutes)

    // 4. Verificacion puntual
    if core.CronMatch(sched, time.Now()) {
        fmt.Println("would trigger now")
    }
}

Fronteras del grupo

NO cubre:

  • Persistencia de schedules (vive en BD de quien lo use: apps/dag_engine/store/).
  • Spawn/wait de procesos (eso es process_*_go_infra).
  • Sintaxis Quartz extendida con ? o anos. Solo soporta los 5 campos estandar + aliases @hourly/@daily/@weekly/@monthly/@yearly.
  • Timezones — todo se evalua en time.Local del proceso. Si necesitas TZ explicita, parsea fuera y traduce.
  • Sintaxis especial de Kubernetes CronJob (segundos opcionales en el primer campo).
  • DAG orchestration / DAG runs (consume estas funciones via apps/dag_engine).

Prerequisitos

  • Go stdlib. Sin dependencias externas en ninguna funcion del grupo.
  • Tipo compartido cron_schedule_go_core (struct con Minute/Hour/Day/Month/Weekday como []int expandidos).

Notas

  • cron_match esta tageada pendiente-usar — sin consumidores actuales aparte del propio paquete. Si se incorpora a next_cron_time como optimizacion -> quitar tag.
  • cron_explain mantiene contrato simple: si el patron no encaja en los reconocidos, devuelve el expr crudo sin error. Apto para UI fallback.
  • Para anadir nueva funcion al grupo: anadir tag scheduler al tags: del frontmatter, anadir fila a la tabla arriba, actualizar N en docs/capabilities/INDEX.md.

Consumidores actuales

  • apps/dag_engineparse_cron_expr_go_core, next_cron_time_go_core (+ cron_ticker_go_infra adyacente).
  • cpp/apps/dag_engine_ui — tab Schedule consume /api/dags expuesto por dag_engine; via backend usa estas funciones.
  • Candidato futuro: cron_explain_go_core en dag_engine /api/dags (anadir campo schedule_human al JSON response) para que la UI no tenga que duplicar logica.