Files
kenjreno ca1243c396 v0.1.0: consolidate intermediate tags into single fresh release
Wipes v0.1.0/v0.1.1 history.  fpc-cron hadn't shipped to any
external consumer yet; the rebuild against fpc-db v0.4.0 was
inline development noise.  This commit + tag is the clean public
starting point.

CRON_VERSION reset to 0.1.0.  CHANGELOG rewritten as a single
0.1.0 entry covering the full library surface as it stands now.
2026-05-06 11:32:25 -07:00

5.6 KiB

Changelog

All notable changes to fpc-cron are recorded here. Every release tag (vX.Y.Z) points at the commit that bumped CRON_VERSION in src/cron.version.pas. Downstream consumers should pin by tag, not commit hash.

Semver intent:

  • major — breaks callers (API removal, signature change)
  • minor — additive features
  • patch — bug fixes, internal cleanups

0.1.0 — 2026-05-06

Initial public release. Cron + interval task runner extracted from canonical Fastway TFWScheduler (fw_scheduler.pas, 1093 lines) per feedback_copy_dont_reinterpret.md. Cron parser bodies are byte-identical to canonical after the type-rename normalisation.

Added

  • cron.runner.TCron — task runner thread, public surface:
    • Create(APool, ARunTask=nil, AGetExtraTasks=nil, ALogger=nil) — constructs in suspended state; declares schema, loads tasks, runs SyncPluginTasks.
    • RegisterSystemTask(AName, AProc) — register a callback for a system/<name> task (replaces canonical's hardcoded case-table).
    • RefreshTasks / RunTaskNow(ATaskID).
    • GetTasksJSON: TJSONArray / GetTaskJSON(ATaskID): TJSONObject.
    • UpdateTask(ATaskID, AUpdates): Boolean — apply enabled / schedule_type / interval_seconds / cron_expr changes, persists to DB.
    • Running: Boolean.
    • class function ParseCronField(AField, AMin, AMax): TBits
    • class function MatchesCron(ACronExpr, ATime): Boolean
    • Typed observer properties: OnTaskStart / OnTaskComplete / OnTaskRegistered / OnPluginOrphaned / OnThreadStart / OnThreadStop.
  • cron.typesTCronTaskKind, TCronTask, TRunTaskProc, TGetExtraTasksFunc, TSystemTaskProc.
  • cron.events — typed observer callback types (TCronOnTaskStart, ...) following the bp.events / cm.events pattern.
  • cron.runner.BuildSystemSchedulerSpec(ANowExpr): TDBTable and BuildSchedulerLogSpec: TDBTabledatabase.TDBTable specs mirroring canonical Fastway fw_schema.pas's BuildSystemScheduler / BuildSchedulerLog.
  • cron.versionCRON_VERSION semver constants.

Adjustments from canonical (the only behaviour-preserving

changes)

Canonical fpc-cron
TFWScheduler TCron
TFWSchedulerTask TCronTask
TFWSchedulerTaskKind TCronTaskKind
TRunPluginTaskProc TRunTaskProc
TGetPluginTasksFunc TGetExtraTasksFunc
  • uses clause swaps: drops fw_consts / fw_log / fw_config / fw_database / fw_plugin_api / fw_plugin_updates / fw_plugin_host / dbapi_consts / dbapi_dialect; adds log.types (fpc-log), database.dialect / database.schema / database.pool (fpc-db v0.1.0), cron.types / cron.events.
  • Global DB replaced with TDBPool parameter on Create.
  • EventBus.Fire(...) calls replaced with typed observer callbacks (assignable as properties on TCron). Same per-library typed-callback pattern as fpc-binkp's bp.events and fpc-comet's cm.events.
  • fw_log.Log.X(...) calls routed through optional log.types.TLogProc callback with Category='cron'.
  • DoWalCheckpointTruncate (SQLite + Fastway specific) and the hardcoded case ATaskName system-task table lifted out — consumers register their own system tasks via RegisterSystemTask.
  • No global Scheduler singleton — consumer creates own.
  • ParseCronField / MatchesCron promoted from private instance methods to class function for testability; bodies byte-verbatim from canonical.

Behaviours preserved verbatim (per the COPY rule)

  • LoadTasksFromDB / SyncPluginTasks / UpdateTaskInDB / LogTaskRun hit the database directly.
  • 5-position cron parser (*, */N, a,b,c, a-b, a-b/N, literal).
  • Cron expressions in local time; UTC at storage time.
  • UTCNow = LocalTimeToUniversal(Now) for every persisted timestamp.
  • Schedule-miss-on-long-task: next firing is delay AFTER previous run returned.
  • TThread + PRTLEvent + 1-second wake loop.
  • Suspended-Create + .Start.
  • SyncPluginTasks orphan cleanup.
  • Event names through bus bridge: 'scheduler.task_start' and 'scheduler.task_result' (canonical literals).
  • DB table names system_scheduler and scheduler_log kept verbatim (Fastway database is reusable as-is).

Known issues inherited verbatim

  • MatchesCron allocates the five TBits field-bit-arrays before its try/finally; if ParseCronField raises on field 2..5, earlier TBits instances leak. Negligible real-world impact.
  • MatchesCron calls DecodeDateFully(ATime, Mn, Hr, Dom, Dow) whose results are immediately overwritten by the next four calls. Cosmetic.

Tests

73 assertions across 23 scenarios:

  • tests/test_cron.pas — 37 pure-cron assertions.
  • tests/test_runner.pas — 36 SQLite-backed end-to-end: Init, NextRun-recalc, RunTaskNow, SyncPluginTasks add + orphan, IntervalFires, SystemTaskFires, SystemTaskFailureRecorded, UpdateTask-disables, RefreshTasks, typed observer callbacks fire, cron task executes through runner, two runners on one pool (idempotent DeclareTable).

Examples

  • examples/interval_task.pas — 5-second interval task.
  • examples/cron_task.pas — daily 3 AM cron task.

Build and test

bash build.sh        # compile every src/*.pas
bash run_tests.sh    # build + tests + examples

fpc.cfg provides multi-target FPC config.

Dependencies

  • fpc-log v0.1.0 — log.types.TLogProc
  • fpc-db v0.1.0 — database.{dialect,schema,pool}