Skip to content

Commit ec3728d

Browse files
authored
Merge pull request #156 from Icinga/use-ipl-scheduler
Use ipl scheduler
2 parents 73dae07 + a656c35 commit ec3728d

16 files changed

+260
-428
lines changed

Diff for: application/clicommands/ScheduleCommand.php

+98-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@
44

55
namespace Icinga\Module\Reporting\Clicommands;
66

7+
use DateTime;
8+
use Exception;
9+
use Icinga\Application\Logger;
710
use Icinga\Module\Reporting\Cli\Command;
8-
use Icinga\Module\Reporting\Scheduler;
11+
use Icinga\Module\Reporting\Model;
12+
use Icinga\Module\Reporting\Report;
13+
use Icinga\Module\Reporting\Schedule;
14+
use ipl\Scheduler\Contract\Frequency;
15+
use ipl\Scheduler\Contract\Task;
16+
use ipl\Scheduler\Scheduler;
17+
use React\EventLoop\Loop;
18+
use React\Promise\ExtendedPromiseInterface;
19+
use Throwable;
920

1021
class ScheduleCommand extends Command
1122
{
@@ -18,8 +29,92 @@ class ScheduleCommand extends Command
1829
*/
1930
public function runAction()
2031
{
21-
$scheduler = new Scheduler($this->getDb());
32+
$scheduler = new Scheduler();
33+
$this->attachJobsLogging($scheduler);
2234

23-
$scheduler->run();
35+
/** @var Schedule[] $runningSchedules */
36+
$runningSchedules = [];
37+
// Check for configuration changes every 5 minutes to make sure new jobs are scheduled, updated and deleted
38+
// jobs are cancelled.
39+
$watchdog = function () use (&$watchdog, $scheduler, &$runningSchedules) {
40+
$schedules = $this->fetchSchedules();
41+
$outdated = array_diff_key($runningSchedules, $schedules);
42+
foreach ($outdated as $schedule) {
43+
Logger::info(
44+
'Removing %s as it either no longer exists in the database or its config has been changed',
45+
$schedule->getName()
46+
);
47+
48+
$scheduler->remove($schedule);
49+
}
50+
51+
$newSchedules = array_diff_key($schedules, $runningSchedules);
52+
foreach ($newSchedules as $schedule) {
53+
$config = $schedule->getConfig();
54+
$frequency = $config['frequency'];
55+
56+
try {
57+
/** @var Frequency $type */
58+
$type = $config['frequencyType'];
59+
$frequency = $type::fromJson($frequency);
60+
} catch (Exception $err) {
61+
Logger::error(
62+
'%s has invalid schedule expression %s: %s',
63+
$schedule->getName(),
64+
$frequency,
65+
$err->getMessage()
66+
);
67+
68+
continue;
69+
}
70+
71+
$scheduler->schedule($schedule, $frequency);
72+
}
73+
74+
$runningSchedules = $schedules;
75+
76+
Loop::addTimer(5 * 60, $watchdog);
77+
};
78+
Loop::futureTick($watchdog);
79+
}
80+
81+
/**
82+
* Fetch schedules from the database
83+
*
84+
* @return Schedule[]
85+
*/
86+
protected function fetchSchedules(): array
87+
{
88+
$schedules = [];
89+
$query = Model\Schedule::on($this->getDb())->with(['report.timeframe', 'report']);
90+
91+
foreach ($query as $schedule) {
92+
$schedule = Schedule::fromModel($schedule, Report::fromModel($schedule->report));
93+
$schedules[$schedule->getChecksum()] = $schedule;
94+
}
95+
96+
return $schedules;
97+
}
98+
99+
protected function attachJobsLogging(Scheduler $scheduler)
100+
{
101+
$scheduler->on(Scheduler::ON_TASK_FAILED, function (Task $job, Throwable $e) {
102+
Logger::error('Failed to run job %s: %s', $job->getName(), $e->getMessage());
103+
Logger::debug($e->getTraceAsString());
104+
});
105+
106+
$scheduler->on(Scheduler::ON_TASK_RUN, function (Task $job, ExtendedPromiseInterface $_) {
107+
Logger::info('Running job %s', $job->getName());
108+
});
109+
110+
$scheduler->on(Scheduler::ON_TASK_SCHEDULED, function (Task $job, DateTime $dateTime) {
111+
Logger::info('Scheduling job %s to run at %s', $job->getName(), $dateTime->format('Y-m-d H:i:s'));
112+
});
113+
114+
$scheduler->on(Scheduler::ON_TASK_EXPIRED, function (Task $task, DateTime $dateTime) {
115+
Logger::info(
116+
sprintf('Detaching expired job %s at %s', $task->getName(), $dateTime->format('Y-m-d H:i:s'))
117+
);
118+
});
24119
}
25120
}

Diff for: application/controllers/ReportController.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Icinga\Module\Reporting\Web\Forms\ScheduleForm;
1515
use Icinga\Module\Reporting\Web\Forms\SendForm;
1616
use Icinga\Module\Reporting\Web\Widget\CompatDropdown;
17+
use Icinga\Web\Notification;
1718
use ipl\Html\Error;
1819
use ipl\Stdlib\Filter;
1920
use ipl\Web\Url;
@@ -149,14 +150,30 @@ public function scheduleAction()
149150
$this->assertPermission('reporting/schedules');
150151
$this->addTitleTab($this->translate('Schedule'));
151152

152-
$form = ScheduleForm::fromReport($this->report)
153-
->setAction((string) Url::fromRequest())
154-
->on(ScheduleForm::ON_SUCCESS, function () {
153+
$form = ScheduleForm::fromReport($this->report);
154+
$form->setAction((string) Url::fromRequest())
155+
->on(ScheduleForm::ON_SUCCESS, function () use ($form) {
156+
$pressedButton = $form->getPressedSubmitElement()->getName();
157+
if ($pressedButton === 'remove') {
158+
Notification::success($this->translate('Removed schedule successfully'));
159+
} elseif ($pressedButton === 'send') {
160+
Notification::success($this->translate('Report sent successfully'));
161+
} elseif ($this->report->getSchedule() !== null) {
162+
Notification::success($this->translate('Updated schedule successfully'));
163+
} else {
164+
Notification::success($this->translate('Created schedule successfully'));
165+
}
166+
155167
$this->redirectNow("reporting/report?id={$this->report->getId()}");
156168
})
157169
->handleRequest($this->getServerRequest());
158170

159171
$this->addContent($form);
172+
173+
$parts = $form->getPartUpdates();
174+
if (! empty($parts)) {
175+
$this->sendMultipartUpdate(...$parts);
176+
}
160177
}
161178

162179
public function downloadAction()

Diff for: doc/02-Installation.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* PHP (>= 7.0)
66
* Icinga Web 2 (>= 2.9)
77
* Icinga Web 2 libraries:
8-
* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.8)
8+
* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.12)
99
* [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.10)
1010
* Icinga Web 2 modules:
1111
* [Icinga PDF Export](https://github.com/Icinga/icingaweb2-module-pdfexport) (>= 0.10)
@@ -16,7 +16,7 @@
1616

1717
### MySQL / MariaDB
1818

19-
The module needs a MySQL/MariaDB database with the schema that's provided in the `etc/schema/mysql.sql` file.
19+
The module needs a MySQL/MariaDB database with the schema that's provided in the `etc/schema/mysql.schema.sql` file.
2020

2121
Example command for creating the MySQL/MariaDB database. Please change the password:
2222

@@ -28,12 +28,12 @@ GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, CREATE VIEW, INDEX, EXECUTE
2828
After, you can import the schema using the following command:
2929

3030
```
31-
mysql -p -u root reporting < schema/mysql.sql
31+
mysql -p -u root reporting < schema/mysql.schema.sql
3232
```
3333

3434
## PostgreSQL
3535

36-
The module needs a PostgreSQL database with the schema that's provided in the `etc/schema/postgresql.sql` file.
36+
The module needs a PostgreSQL database with the schema that's provided in the `etc/schema/pgsql.schema.sql` file.
3737

3838
Example command for creating the PostgreSQL database. Please change the password:
3939

@@ -49,7 +49,7 @@ CREATE DATABASE reporting
4949
After, you can import the schema using the following command:
5050

5151
```
52-
psql -U reporting reporting -a -f schema/postgresql.sql
52+
psql -U reporting reporting -a -f schema/pgsql.schema.sql
5353
```
5454

5555
## Module Installation

Diff for: doc/80-Upgrading.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ Usually the only manual steps involved are schema updates for the database.
77

88
Icinga Reporting version 0.10.0 requires a schema update for the database.
99
A new table `template`, linked to table `report`, has been introduced.
10-
Please find the upgrade script in **schema/mysql-migrations**.
10+
Please find the upgrade script in **schema/mysql-upgrades**.
1111

1212
You may use the following command to apply the database schema upgrade file:
1313

1414
```
15-
# mysql -u root -p reporting <schema/mysql-migrations/v0.10.0.sql
15+
# mysql -u root -p reporting <schema/mysql-upgrades/0.10.0.sql
1616
```
1717

1818
## Upgrading to Version 0.9.1
@@ -26,5 +26,5 @@ Please find the upgrade script in **schema/mysql-migrations**.
2626
You may use the following command to apply the database schema upgrade file:
2727

2828
```
29-
# mysql -u root -p reporting <schema/mysql-migrations/v0.9.1.sql
29+
# mysql -u root -p reporting <schema/mysql-upgrades/0.9.1.sql
3030
```

Diff for: library/Reporting/Report.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public static function fromModel(Model\Report $reportModel): self
7777

7878
$schedule = $reportModel->schedule->first();
7979
if ($schedule !== null) {
80-
$report->schedule = Schedule::fromModel($schedule)->setReport($report);
80+
$report->schedule = Schedule::fromModel($schedule, $report);
8181
}
8282

8383
return $report;

0 commit comments

Comments
 (0)