Skip to content

Commit 7cd4c7f

Browse files
committed
[+] check cron syntax and next runs asynchronously with 1s delay
1 parent a5d4b8d commit 7cd4c7f

File tree

3 files changed

+44
-24
lines changed

3 files changed

+44
-24
lines changed

forms/framecroneditor.lfm

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
inherited frmCronEditor: TfrmCronEditor
22
Width = 472
33
ClientWidth = 472
4-
object pnlEditor: TPanel[0]
4+
inherited pnlButtons: TPanel
5+
Width = 472
6+
ClientWidth = 472
7+
inherited btnCancel: TButton
8+
OnClick = FrameExit
9+
OnExit = nil
10+
end
11+
end
12+
object pnlEditor: TPanel[1]
513
Left = 0
614
Height = 304
715
Top = 0
@@ -94,12 +102,10 @@ inherited frmCronEditor: TfrmCronEditor
94102
ParentColor = False
95103
end
96104
end
97-
inherited pnlButtons: TPanel[1]
98-
Width = 472
99-
ClientWidth = 472
100-
inherited btnCancel: TButton
101-
OnClick = FrameExit
102-
OnExit = nil
103-
end
105+
object timerChange: TTimer[2]
106+
Enabled = False
107+
OnTimer = timerChangeTimer
108+
Left = 416
109+
Top = 88
104110
end
105111
end

forms/framecroneditor.pas

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ TfrmCronEditor = class(TBaseFrame)
2222
lblMonth: TLabel;
2323
mmRuns: TMemo;
2424
pnlEditor: TPanel;
25+
timerChange: TTimer;
2526
procedure edCronChange(Sender: TObject);
27+
procedure timerChangeTimer(Sender: TObject);
2628
private
2729

2830
public
@@ -40,39 +42,44 @@ implementation
4042
{ TfrmCronEditor }
4143

4244
procedure TfrmCronEditor.edCronChange(Sender: TObject);
45+
begin
46+
timerChange.Enabled := True; //start timer to update next runs
47+
end;
48+
49+
procedure TfrmCronEditor.timerChangeTimer(Sender: TObject);
4350
var
4451
ValidCron: boolean;
4552
S: string;
53+
Output: string;
4654
const
4755
cronRE = '^(((\d+,)+\d+|(\d+(\/|-)\d+)|(\*(\/|-)\d+)|\d+|\*) +){4}'+
4856
'(((\d+,)+\d+|(\d+(\/|-)\d+)|(\*(\/|-)\d+)|\d+|\*) ?)$';
4957
sqlCronRuns = 'SELECT to_char(r.r, ''FMDay, FMDD FMMon YYYY at HH24:MI:SS'') FROM '+
5058
'generate_series(now(), now() + 10 * :cron :: interval, :cron :: interval) AS r(r) LIMIT 10';
5159
sqlIntervalRuns = 'SELECT to_char(r.r, ''FMDay, FMDD FMMon YYYY at HH24:MI:SS'') FROM '+
52-
'timetable.cron_runs(now(), $1) AS r(r) LIMIT 10';
60+
'timetable.cron_runs(now(), :cron) AS r(r) LIMIT 10';
5361
minIntervalLen = length('@every '); // @ modifier and at least one space char
5462
begin
63+
timerChange.Enabled := False;
5564
S := edCron.Text;
5665
ValidCron := S.Trim() = '@reboot';
5766
if not ValidCron then
5867
if S.StartsWith('@every ') or S.StartsWith('@after ') then //special values
59-
begin
60-
ValidCron := (S.Length > minIntervalLen) and dmPgEngine.IsCronValueValid(S);
61-
if ValidCron then
62-
mmRuns.Text := dmPgEngine.SelectSQL(sqlCronRuns, [S.Substring(minIntervalLen)]);
63-
end
68+
ValidCron := (S.Length > minIntervalLen)
69+
and dmPgEngine.IsCronValueValid(S)
70+
and dmPgEngine.SelectSQL(sqlCronRuns, [S.Substring(minIntervalLen)], Output)
6471
else
6572
with TRegExpr.Create(cronRE) do
6673
try
67-
ValidCron := Exec(S);
68-
if ValidCron then
69-
mmRuns.Text := dmPgEngine.SelectSQL(sqlIntervalRuns, [S]);
74+
ValidCron := Exec(S) and dmPgEngine.SelectSQL(sqlIntervalRuns, [S], Output);
7075
finally
7176
Free();
7277
end;
78+
mmRuns.Text := Output;
7379
if ValidCron then edCron.Color := clDefault else edCron.Color := clRed;
7480
end;
7581

82+
7683
function TfrmCronEditor.GetEditorValue: string;
7784
begin
7885
Exit(edCron.Text);

udatamodule.pas

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ TdmPgEngine = class(TDataModule)
3939
procedure Disconnect;
4040
function IsCronValueValid(const S: string): boolean;
4141
function IsConnected: boolean;
42-
function SelectSQL(const sql: string; params: array of string): string;
42+
function SelectSQL(const sql: string; params: array of string; out Output: string): boolean;
4343
procedure MoveTaskUp(const ATaskID: integer);
4444
procedure MoveTaskDown(const ATaskID: integer);
4545
function IsTaskDeleteAllowed: boolean;
@@ -187,13 +187,13 @@ function TdmPgEngine.IsConnected: boolean;
187187
Result := qryChains.Active and qryTasks.Active;
188188
end;
189189

190-
function TdmPgEngine.SelectSQL(const sql: string; params: array of string): string;
190+
function TdmPgEngine.SelectSQL(const sql: string; params: array of string; out Output: string): boolean;
191191
var
192192
Q: TSQLQuery;
193193
i: Integer;
194-
NewParams: TSQLDBParams;
195194
begin
196-
Result := '';
195+
Result := True;
196+
Output := '';
197197
Q := TSQLQuery.Create(nil);
198198
try
199199
Q.DataBase := connMain;
@@ -205,11 +205,18 @@ function TdmPgEngine.SelectSQL(const sql: string; params: array of string): stri
205205
Q.Open;
206206
while not Q.EOF do
207207
begin
208-
Result := Result + Q.Fields[0].AsString + LineEnding;
208+
Output := Output + Q.Fields[0].AsString + LineEnding;
209209
Q.Next;
210210
end;
211-
except on E: exception do
212-
connMainLog(connMain, detCustom, E.Message);
211+
except
212+
on E: Exception do
213+
begin
214+
Result := False;
215+
if E is EPQDatabaseError then
216+
Output := EPQDatabaseError(E).MESSAGE_PRIMARY
217+
else
218+
Output := E.Message;
219+
end;
213220
end;
214221
Q.Close;
215222
finally

0 commit comments

Comments
 (0)