fix(#29): validate cron zone, warn when basepull is off, document schedulers #31

Merged
KofTwentyTwo merged 4 commits from feature/GH-29-cron-basepull-scheduler-docs into develop 2026-10-12 11:00:59 +00:00
KofTwentyTwo commented 2026-10-10 00:23:30 +00:00 (Migrated from github.com)

Summary

  • Cron time zone. A reconcileCronExpression without reconcileCronTimeZoneId passed the QBit's validation, then QQQ's QInstanceValidator.validateScheduleMetaData failed startup with Process quickSearchReconcileIndex, schedule: a cron schedule must specify a cronTimeZoneId. QQQ has no default zone, so the QBit does not invent one (a silent UTC default would move run times for hosts that meant local time). validate() now rejects the missing zone naming both fields, and applies the checks QQQ applies to every cron schedule: Quartz CronExpression.validateExpression and a zone from TimeZone.getAvailableIDs().
  • Cron scheduler type. validate() also rejects a cron when the named scheduler is in the instance and does not support cron (QSchedulerMetaData.supportsCronSchedules()). Only QuartzSchedulerMetaData does; SimpleScheduler reads repeatSeconds and fails with an NPE when the schedule manager starts.
  • Basepull warning. Config-driven tables without their basepull timestamp field now log the same startup warning as annotated tables, once per table, through one shared helper (tableName and timestampField as log pairs). A config-driven field explicitly set to null is an opt-out and gets no warning, matching an annotation with an empty field.
  • Docs. README (new Scheduling section, config reference) and docs/MIGRATION-1.0.md (step 4, new Scheduling section, behaviour note) say that schedules run only when the host starts through com.kingsrook.qqq.middleware.javalin.QApplicationLauncher (qqq-middleware-javalin 4.1.0-RC.1, QApplicationLauncher.run(app, config) starts the server, then QScheduleManager when anything is scheduled, then runtime services), and that a reconcile cron needs a Quartz scheduler and a time zone ID.

Testing

  • TDD: the five new tests failed before the change (validation: missing zone, invalid cron or zone, cron on a simple scheduler; producer: produce fails on a missing zone, and the config-driven warning).
  • Updated two tests that asserted a cron on a simple scheduler with no zone was valid; they now use a Quartz scheduler and a zone.
  • A throwaway probe (not committed) ran QQQ's QInstanceValidator on the reconcile process with a cron and no zone and got the startup error quoted above.
  • CI=true ./mvnw verify: 358 unit tests and 19 integration tests pass, JaCoCo coverage checks met.

Closes #29

## Summary - **Cron time zone.** A `reconcileCronExpression` without `reconcileCronTimeZoneId` passed the QBit's validation, then QQQ's `QInstanceValidator.validateScheduleMetaData` failed startup with `Process quickSearchReconcileIndex, schedule: a cron schedule must specify a cronTimeZoneId`. QQQ has no default zone, so the QBit does not invent one (a silent UTC default would move run times for hosts that meant local time). `validate()` now rejects the missing zone naming both fields, and applies the checks QQQ applies to every cron schedule: Quartz `CronExpression.validateExpression` and a zone from `TimeZone.getAvailableIDs()`. - **Cron scheduler type.** `validate()` also rejects a cron when the named scheduler is in the instance and does not support cron (`QSchedulerMetaData.supportsCronSchedules()`). Only `QuartzSchedulerMetaData` does; `SimpleScheduler` reads `repeatSeconds` and fails with an NPE when the schedule manager starts. - **Basepull warning.** Config-driven tables without their basepull timestamp field now log the same startup warning as annotated tables, once per table, through one shared helper (`tableName` and `timestampField` as log pairs). A config-driven field explicitly set to null is an opt-out and gets no warning, matching an annotation with an empty field. - **Docs.** README (new Scheduling section, config reference) and `docs/MIGRATION-1.0.md` (step 4, new Scheduling section, behaviour note) say that schedules run only when the host starts through `com.kingsrook.qqq.middleware.javalin.QApplicationLauncher` (`qqq-middleware-javalin` 4.1.0-RC.1, `QApplicationLauncher.run(app, config)` starts the server, then `QScheduleManager` when anything is scheduled, then runtime services), and that a reconcile cron needs a Quartz scheduler and a time zone ID. ## Testing - TDD: the five new tests failed before the change (validation: missing zone, invalid cron or zone, cron on a simple scheduler; producer: produce fails on a missing zone, and the config-driven warning). - Updated two tests that asserted a cron on a simple scheduler with no zone was valid; they now use a Quartz scheduler and a zone. - A throwaway probe (not committed) ran QQQ's `QInstanceValidator` on the reconcile process with a cron and no zone and got the startup error quoted above. - `CI=true ./mvnw verify`: 358 unit tests and 19 integration tests pass, JaCoCo coverage checks met. Closes #29
Sign in to join this conversation.