305 lines
8.5 KiB
Markdown
305 lines
8.5 KiB
Markdown
# fpc-cron — API reference
|
|
|
|
Every callable the library exposes, with parameters, return
|
|
values, and runnable examples. See
|
|
[`architecture.md`](architecture.md) for the big picture and
|
|
[`DEVELOPER_GUIDE.md`](DEVELOPER_GUIDE.md) for the
|
|
consumer-oriented walkthrough.
|
|
|
|
## Contents
|
|
|
|
- [Quick start](#quick-start)
|
|
- [Types (`cron.types`)](#types)
|
|
- [Events (`cron.events`)](#events)
|
|
- [Schema specs (`cron.runner`)](#schema-specs)
|
|
- [TCron](#tcron)
|
|
- [Create](#tcroncreate)
|
|
- [Destroy](#tcrondestroy)
|
|
- [RegisterSystemTask](#tcronregistersystemtask)
|
|
- [RefreshTasks](#tcronrefreshtasks)
|
|
- [RunTaskNow](#tcronruntasknow)
|
|
- [GetTasksJSON / GetTaskJSON](#tcrongettasksjson)
|
|
- [UpdateTask](#tcronupdatetask)
|
|
- [Running (property)](#tcronrunning)
|
|
- [OnTaskStart / OnTaskComplete / OnTaskRegistered / OnPluginOrphaned / OnThreadStart / OnThreadStop](#tcronon)
|
|
- [ParseCronField (class function)](#tcronparsecronfield)
|
|
- [MatchesCron (class function)](#tcronmatchescron)
|
|
- [Version constants](#version-constants)
|
|
|
|
---
|
|
|
|
## Quick start
|
|
|
|
```pascal
|
|
uses
|
|
Classes, SysUtils, fpjson, DateUtils,
|
|
log.types,
|
|
database.types, database.pool,
|
|
cron.types, cron.events, cron.runner;
|
|
|
|
var
|
|
Pool: TDBPool;
|
|
C: TCron;
|
|
begin
|
|
Pool := TDBPool.Create;
|
|
Pool.Init(dbSQLite, '/tmp/cron.sqlite3');
|
|
try
|
|
C := TCron.Create(Pool, @MyHost.RunTask, nil, @MyHost.HandleLog);
|
|
try
|
|
C.OnTaskComplete := @MyHost.HandleTaskComplete;
|
|
C.RegisterSystemTask('cleanup', @MyHost.RunCleanup);
|
|
C.Start;
|
|
...
|
|
C.Terminate;
|
|
finally
|
|
C.Free;
|
|
end;
|
|
finally
|
|
Pool.Free;
|
|
end;
|
|
end.
|
|
```
|
|
|
|
## Types
|
|
|
|
`cron.types`:
|
|
|
|
```pascal
|
|
type
|
|
TCronTaskKind = (stkInterval, stkCron);
|
|
|
|
TCronTask = record
|
|
ID: Integer;
|
|
TaskName: string;
|
|
PluginName: string;
|
|
Description: string;
|
|
Category: string;
|
|
Kind: TCronTaskKind;
|
|
IntervalSeconds: Integer;
|
|
CronExpr: string;
|
|
Enabled: Boolean;
|
|
LastRun: TDateTime;
|
|
NextRun: TDateTime;
|
|
LastResult: string;
|
|
LastError: string;
|
|
RunCount: Integer;
|
|
FailCount: Integer;
|
|
UserModified: Boolean;
|
|
IsRunning: Boolean;
|
|
end;
|
|
|
|
TRunTaskProc = procedure(const APluginName, ATaskName: string) of object;
|
|
TGetExtraTasksFunc = function: TJSONArray of object;
|
|
TSystemTaskProc = procedure(const ATaskName: string) of object;
|
|
```
|
|
|
|
The logger type is `log.types.TLogProc`, defined in fpc-log.
|
|
|
|
## Events
|
|
|
|
`cron.events` defines the typed observer callbacks (same pattern
|
|
as fpc-binkp's `bp.events` and fpc-comet's `cm.events`):
|
|
|
|
```pascal
|
|
type
|
|
TCronOnTaskStart = procedure(const APluginName, ATaskName: string) of object;
|
|
|
|
TCronOnTaskComplete = procedure(const APluginName, ATaskName: string;
|
|
ASuccess: Boolean; ADurationMs: Integer;
|
|
const AError: string) of object;
|
|
|
|
TCronOnTaskRegistered = procedure(const APluginName, ATaskName: string;
|
|
AIntervalSeconds: Integer) of object;
|
|
|
|
TCronOnPluginOrphaned = procedure(const APluginName: string) of object;
|
|
|
|
TCronOnThreadStart = procedure of object;
|
|
|
|
TCronOnThreadStop = procedure of object;
|
|
```
|
|
|
|
All callbacks are `of object`. `nil` is always valid (no-op).
|
|
|
|
## Schema specs
|
|
|
|
```pascal
|
|
function BuildSystemSchedulerSpec(const ANowExpr: string): TDBTable;
|
|
function BuildSchedulerLogSpec: TDBTable;
|
|
```
|
|
|
|
Return fpc-db `TDBTable` specs for the two runner-owned tables.
|
|
Use these to declare schema independently of `TCron.Create`:
|
|
|
|
```pascal
|
|
APool.DeclareTable(BuildSystemSchedulerSpec(APool.Dialect.NowExpr));
|
|
APool.DeclareTable(BuildSchedulerLogSpec);
|
|
```
|
|
|
|
The names mirror canonical Fastway `fw_schema.pas`'s
|
|
`BuildSystemScheduler` / `BuildSchedulerLog` so a Fastway
|
|
database is reusable without migration.
|
|
|
|
## TCron
|
|
|
|
`TCron = class(TThread)`. Created suspended; caller calls
|
|
`.Start` to begin the wake loop.
|
|
|
|
### `TCron.Create`
|
|
|
|
```pascal
|
|
constructor Create(APool: TDBPool;
|
|
ARunTask: TRunTaskProc = nil;
|
|
AGetExtraTasks: TGetExtraTasksFunc = nil;
|
|
ALogger: TLogProc = nil);
|
|
```
|
|
|
|
- `APool` — required. fpc-db pool the runner reads/writes its
|
|
two tables on. Raises if `nil`.
|
|
- `ARunTask` — invoked for every non-system task. `nil` means
|
|
non-system tasks fail with `'No plugin task runner available'`.
|
|
- `AGetExtraTasks` — invoked at `Create` and on `RefreshTasks`
|
|
to discover plugin tasks. `nil` means
|
|
`SyncPluginTasks` is a no-op.
|
|
- `ALogger` — `log.types.TLogProc`. `nil` means silent.
|
|
|
|
`Create` calls `Pool.DeclareTable` for both schema specs, runs
|
|
`LoadTasksFromDB`, and runs `SyncPluginTasks`. Returns a
|
|
*suspended* thread — caller must call `.Start`.
|
|
|
|
### `TCron.Destroy`
|
|
|
|
If the wake loop is running, `Destroy` calls `Terminate`,
|
|
fires the stop event, and `WaitFor`s the thread. Then frees
|
|
the lock and the stop event. Safe to call from any thread.
|
|
|
|
### `TCron.RegisterSystemTask`
|
|
|
|
```pascal
|
|
procedure RegisterSystemTask(const AName: string; AProc: TSystemTaskProc);
|
|
```
|
|
|
|
Register a callback for a `system/<AName>` task. Calling twice
|
|
with the same name replaces the previous entry. Replaces
|
|
canonical Fastway's hardcoded `case ATaskName of` table.
|
|
|
|
If a `plugin_name='system'` task fires whose name isn't
|
|
registered, the runner logs `'unknown system task: <name>'` at
|
|
`llWarn` and moves on.
|
|
|
|
### `TCron.RefreshTasks`
|
|
|
|
```pascal
|
|
procedure RefreshTasks;
|
|
```
|
|
|
|
Reload from the DB and re-run `SyncPluginTasks`. Use after
|
|
inserting tasks externally, or after the supplier callback's
|
|
return value has changed. Recomputes `NextRun` for every
|
|
enabled task.
|
|
|
|
### `TCron.RunTaskNow`
|
|
|
|
```pascal
|
|
procedure RunTaskNow(ATaskID: Integer);
|
|
```
|
|
|
|
Synchronously run one task by row id. Updates `LastRun`,
|
|
`RunCount`, `FailCount`, `NextRun`, writes a `scheduler_log`
|
|
row, fires `OnTaskStart` + `OnTaskComplete`. Useful for "run
|
|
now" buttons in admin UIs.
|
|
|
|
### `TCron.GetTasksJSON`
|
|
|
|
```pascal
|
|
function GetTasksJSON: TJSONArray;
|
|
function GetTaskJSON(ATaskID: Integer): TJSONObject;
|
|
```
|
|
|
|
Snapshot the in-memory task table. `GetTaskJSON` returns `nil`
|
|
if the task ID isn't found. Caller owns the returned objects
|
|
(must `Free` them). All `last_run` / `next_run` timestamps are
|
|
formatted as `'yyyy-mm-dd hh:nn:ss'` (UTC); null when unset.
|
|
|
|
### `TCron.UpdateTask`
|
|
|
|
```pascal
|
|
function UpdateTask(ATaskID: Integer; AUpdates: TJSONObject): Boolean;
|
|
```
|
|
|
|
Apply mutations to an existing task and persist to DB.
|
|
Recognised keys in `AUpdates`:
|
|
|
|
- `enabled` (Boolean)
|
|
- `schedule_type` (`'interval'` or `'cron'`)
|
|
- `interval_seconds` (Integer, must be > 0)
|
|
- `cron_expr` (string)
|
|
|
|
Sets `user_modified = 1` (which exempts the row from
|
|
`SyncPluginTasks` orphan cleanup). Recomputes `NextRun`.
|
|
Returns `True` if the task was found, `False` otherwise.
|
|
|
|
### `TCron.Running`
|
|
|
|
```pascal
|
|
property Running: Boolean read FRunning;
|
|
```
|
|
|
|
`True` between `Execute` start and stop.
|
|
|
|
### `TCron.OnTaskStart` etc.
|
|
|
|
```pascal
|
|
property OnTaskStart: TCronOnTaskStart ...;
|
|
property OnTaskComplete: TCronOnTaskComplete ...;
|
|
property OnTaskRegistered: TCronOnTaskRegistered ...;
|
|
property OnPluginOrphaned: TCronOnPluginOrphaned ...;
|
|
property OnThreadStart: TCronOnThreadStart ...;
|
|
property OnThreadStop: TCronOnThreadStop ...;
|
|
```
|
|
|
|
Wire by assignment (`C.OnTaskStart := @Host.HandleStart`).
|
|
Each callback is invoked synchronously on the runner thread.
|
|
`nil` (the default) means no-op.
|
|
|
|
### `TCron.ParseCronField`
|
|
|
|
```pascal
|
|
class function ParseCronField(const AField: string;
|
|
AMin, AMax: Integer): TBits;
|
|
```
|
|
|
|
Parse one cron field (`*`, `*/N`, `a,b,c`, `a-b`, `a-b/N`,
|
|
or a single literal). Returns a `TBits` of size `AMax+1`
|
|
with the matched values set. Caller frees the result.
|
|
|
|
Out-of-range literals are silently dropped.
|
|
|
|
### `TCron.MatchesCron`
|
|
|
|
```pascal
|
|
class function MatchesCron(const ACronExpr: string;
|
|
ATime: TDateTime): Boolean;
|
|
```
|
|
|
|
Test whether a 5-field cron expression matches the given
|
|
`TDateTime`. Returns `False` if `ACronExpr` has fewer than 5
|
|
fields after splitting on whitespace.
|
|
|
|
`ATime` is treated as local time (canonical Fastway behaviour);
|
|
the canonical's `next_run` math converts to UTC after the match.
|
|
|
|
## Version constants
|
|
|
|
In `cron.version`:
|
|
|
|
```pascal
|
|
const
|
|
CRON_VERSION_MAJOR = 0;
|
|
CRON_VERSION_MINOR = 1;
|
|
CRON_VERSION_PATCH = 0;
|
|
CRON_VERSION_STRING = '0.1.0';
|
|
```
|
|
|
|
Bumped together with the git tag. Pin downstream consumers by
|
|
tag, not commit hash.
|