Skip to content

Commit 808a1d2

Browse files
committed
refactor(Datasource\AbstractCronTask): gaps diagnosis
1 parent 59b5cf8 commit 808a1d2

7 files changed

Lines changed: 138 additions & 57 deletions

File tree

install/migration/update_1.1.1_to_1.2.0/06_migrate_automatic_actions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
$task->update([
4242
'id' => $task->getID(),
4343
'itemtype' => 'GlpiPlugin\\Carbon\\DataSource\\CarbonIntensity\\Rte\\CronTask',
44-
'name' => 'Download',
44+
'name' => 'DownloadRte',
4545
]);
4646
}
4747

@@ -54,6 +54,6 @@
5454
$task->update([
5555
'id' => $task->getID(),
5656
'itemtype' => 'GlpiPlugin\\Carbon\\DataSource\\CarbonIntensity\\ElectricityMaps\\CronTask',
57-
'name' => 'Download',
57+
'name' => 'DownloadElectricityMaps',
5858
]);
5959
}

src/CronTask.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,19 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $
7070
if ($item instanceof GlpiCronTask) {
7171
/** @var GlpiCronTask $item */
7272
$cron_task = new self();
73-
$cron_task->showForCronTask($item);
73+
$cron_task->showForCronTask($item, $tabnum);
7474
}
7575
return true;
7676
}
7777

78-
public function showForCronTask(CommonDBTM $item)
78+
public function showForCronTask(CommonDBTM $item, int $tabnum)
7979
{
8080
$itemtype = $item->fields['itemtype'];
8181
if (!in_array($itemtype, CronTaskProvider::getCronTaskTypes())) {
8282
return;
8383
}
8484
$crontask = new $itemtype();
85-
$crontask->showForCronTask($item);
85+
$crontask->showForCronTask($item, $tabnum);
8686
}
8787

8888
/**

src/DataSource/AbstractCronTask.php

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,130 @@
3434

3535
use CommonDBTM;
3636
use CommonGLPI;
37+
use CronTask as GlpiCronTask;
38+
use Glpi\Application\View\TemplateRenderer;
39+
use GlpiPlugin\Carbon\CarbonIntensity;
40+
use GlpiPlugin\Carbon\CronTask;
3741
use GlpiPlugin\Carbon\DataSource\CarbonIntensity\ClientFactory;
3842
use GlpiPlugin\Carbon\Source_Zone;
43+
use GlpiPlugin\Carbon\Toolbox;
44+
use GlpiPlugin\Carbon\Zone;
45+
use RuntimeException;
3946

4047
abstract class AbstractCronTask extends CommonGLPI implements CronTaskInterface
4148
{
4249
protected static string $client_name;
4350

51+
protected static string $downloadMethod;
52+
53+
protected const TAB_DIAGNOSIS = 0;
54+
protected const TAB_CACHE = 1;
55+
56+
4457
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
4558
{
4659
return '';
4760
}
4861

49-
public function showForCronTask(CommonDBTM $item)
62+
public function showForCronTask(CommonDBTM $item, int $tabnum)
63+
{
64+
if ($tabnum === self::TAB_DIAGNOSIS) {
65+
switch ($item->fields['name']) {
66+
case static::$downloadMethod:
67+
$this->showGapsReport();
68+
}
69+
} elseif ($tabnum === self::TAB_CACHE) {
70+
switch ($item->fields['name']) {
71+
case static::$downloadMethod:
72+
// TODO: implement tab to clear cached data in files/ folder
73+
}
74+
}
75+
}
76+
77+
public function showGapsReport()
5078
{
51-
switch ($item->fields['name']) {
52-
case 'Download':
53-
$client = ClientFactory::create(static::$client_name);
54-
$source_name = $client->getSourceName();
55-
foreach ($client->getSupportedZones() as $zone_name) {
56-
$source_zone = new Source_Zone();
57-
if (!$source_zone->getFromDbBySourceAndZone($source_name, $zone_name)) {
58-
continue;
59-
}
60-
if (!$source_zone->fields['is_download_enabled']) {
61-
continue;
62-
}
63-
$source_zone->showGaps();
64-
}
79+
$renderer = TemplateRenderer::getInstance();
80+
$template = <<<TWIG
81+
{% import "components/form/fields_macros.html.twig" as fields %}
82+
{{ fields.largeTitle(__('Gaps in carbon intensity time series', 'carbon')) }}
83+
<div>{{ __('Only zones with download enabled are displayed.', 'carbon') }}</div>
84+
<div>&nbsp;</div>
85+
TWIG;
86+
echo $renderer->renderFromStringTemplate($template);
87+
$oldest_asset_date = (new Toolbox())->getOldestAssetDate();
88+
$client = ClientFactory::create(static::$client_name);
89+
$source_name = $client->getSourceName();
90+
foreach ($client->getSupportedZones() as $zone_name) {
91+
$source_zone = new Source_Zone();
92+
if (!$source_zone->getFromDbBySourceAndZone($source_name, $zone_name)) {
93+
continue;
94+
}
95+
if (!$source_zone->fields['is_download_enabled']) {
96+
continue;
97+
}
98+
$zone_id = $source_zone->fields['plugin_carbon_zones_id'];
99+
$carbon_intensity = new CarbonIntensity();
100+
$entries = $carbon_intensity->findGaps(
101+
$source_zone,
102+
$oldest_asset_date
103+
);
104+
$total = count($entries);
105+
$zone = Zone::getById($zone_id);
106+
107+
$template = <<<TWIG
108+
{% import "components/form/fields_macros.html.twig" as fields %}
109+
{{ fields.smallTitle(__('Gaps for the zone %s', 'carbon')|format(zone_name)) }}
110+
TWIG;
111+
echo $renderer->renderFromStringTemplate($template, ['zone_name' => $zone->fields['name']]);
112+
$renderer->display('components/datatable.html.twig', [
113+
'is_tab' => true,
114+
'nopager' => true,
115+
'nofilter' => true,
116+
'nosort' => true,
117+
'columns' => [
118+
'start' => __('Start'),
119+
'end' => __('End', 'carbon'),
120+
],
121+
'footers' => [
122+
['', '', '', __('Total'), $total, ''],
123+
],
124+
'footer_class' => 'fw-bold',
125+
'entries' => $entries,
126+
'total_number' => $total,
127+
'filtered_number' => $total,
128+
'showmassiveactions' => false,
129+
'massiveactionparams' => [
130+
'num_displayed' => $total,
131+
'container' => 'mass' . static::class . mt_rand(),
132+
],
133+
]);
65134
}
66135
}
136+
137+
/**
138+
* Uniformize download method of carbon intensity clients
139+
* The design of \CronTask requires that each cron task to use a unique method name, across itemtypes
140+
*
141+
* @param string $name
142+
* @param array $arguments
143+
* @return int
144+
*/
145+
public static function __callStatic($name, $arguments)
146+
{
147+
if ($name === 'cron' . static::$downloadMethod) {
148+
return self::cronDownload(...$arguments);
149+
}
150+
throw new RuntimeException('Not implemented');
151+
}
152+
153+
/**
154+
* Automatic action to download carbon intensity from a data source
155+
*
156+
* @return int
157+
*/
158+
public static function cronDownload(GlpiCronTask $task): int
159+
{
160+
$client = ClientFactory::create(static::$client_name);
161+
return CronTask::downloadCarbonIntensityFromSource($task, $client, new CarbonIntensity());
162+
}
67163
}

src/DataSource/CarbonIntensity/ElectricityMaps/CronTask.php

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,26 @@
3434

3535
use CommonGLPI;
3636
use CronTask as GlpiCronTask;
37-
use GlpiPlugin\Carbon\CarbonIntensity;
38-
use GlpiPlugin\Carbon\CronTask as CarbonCronTask;
3937
use GlpiPlugin\Carbon\DataSource\AbstractCronTask;
40-
use GlpiPlugin\Carbon\DataSource\CarbonIntensity\ClientFactory;
4138
use GlpiPlugin\Carbon\DataSource\CronTaskInterface;
4239

4340
class CronTask extends AbstractCronTask implements CronTaskInterface
4441
{
4542
protected static string $client_name = 'ElectricityMaps';
4643

44+
protected static string $downloadMethod = 'DownloadElectricityMaps';
45+
4746
public static function getIcon()
4847
{
4948
return 'fa-solid fa-gears';
5049
}
5150

5251
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
5352
{
54-
return self::createTabEntry(__('Resource diagnosis', 'carbon'), 0);
53+
return [
54+
self::TAB_DIAGNOSIS => self::createTabEntry(__('Resource diagnosis', 'carbon'), 0),
55+
// self::TAB_CACHE => self::createTabEntry(__('Cache', 'carbon'), 0),
56+
];
5557
}
5658

5759
public static function enumerateTasks(): array
@@ -60,7 +62,7 @@ public static function enumerateTasks(): array
6062
return [
6163
[
6264
'itemtype' => self::class,
63-
'name' => 'Download',
65+
'name' => self::$downloadMethod,
6466
'frequency' => DAY_TIMESTAMP / 2,
6567
'options' => [
6668
'mode' => GlpiCronTask::MODE_EXTERNAL,
@@ -82,23 +84,12 @@ public static function enumerateTasks(): array
8284
public static function cronInfo(string $name): array
8385
{
8486
switch ($name) {
85-
case 'Download':
87+
case self::$downloadMethod:
8688
return [
8789
'description' => __('Download carbon emissions from Electricity Maps', 'carbon'),
8890
'parameter' => __('Maximum number of entries to download', 'carbon'),
8991
];
9092
}
9193
return [];
9294
}
93-
94-
/**
95-
* Automatic action for Electricity Maps datasource
96-
*
97-
* @return int
98-
*/
99-
public static function cronDownload(GlpiCronTask $task): int
100-
{
101-
$client = ClientFactory::create(static::$client_name);
102-
return CarbonCronTask::downloadCarbonIntensityFromSource($task, $client, new CarbonIntensity());
103-
}
10495
}

src/DataSource/CarbonIntensity/Rte/CronTask.php

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,29 @@
3434

3535
use CommonGLPI;
3636
use CronTask as GlpiCronTask;
37-
use GlpiPlugin\Carbon\CarbonIntensity;
38-
use GlpiPlugin\Carbon\CronTask as CarbonCronTask;
3937
use GlpiPlugin\Carbon\DataSource\AbstractCronTask;
40-
use GlpiPlugin\Carbon\DataSource\CarbonIntensity\ClientFactory;
4138
use GlpiPlugin\Carbon\DataSource\CronTaskInterface;
4239

40+
/**
41+
* @method int cronDownloadRte(GlpiCronTask $task)
42+
*/
4343
class CronTask extends AbstractCronTask implements CronTaskInterface
4444
{
4545
protected static string $client_name = 'Rte';
4646

47+
protected static string $downloadMethod = 'DownloadRte';
48+
4749
public static function getIcon()
4850
{
4951
return 'fa-solid fa-gears';
5052
}
5153

5254
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
5355
{
54-
return self::createTabEntry(__('Resource diagnosis', 'carbon'), 0);
56+
return [
57+
self::TAB_DIAGNOSIS => self::createTabEntry(__('Resource diagnosis', 'carbon'), 0),
58+
// self::TAB_CACHE => self::createTabEntry(__('Cache', 'carbon'), 0),
59+
];
5560
}
5661

5762
public static function enumerateTasks(): array
@@ -60,7 +65,7 @@ public static function enumerateTasks(): array
6065
return [
6166
[
6267
'itemtype' => self::class,
63-
'name' => 'Download',
68+
'name' => self::$downloadMethod,
6469
'frequency' => DAY_TIMESTAMP,
6570
'options' => [
6671
'mode' => GlpiCronTask::MODE_EXTERNAL,
@@ -82,23 +87,12 @@ public static function enumerateTasks(): array
8287
public static function cronInfo(string $name): array
8388
{
8489
switch ($name) {
85-
case 'Download':
90+
case 'DownloadRte':
8691
return [
8792
'description' => __('Download carbon emissions from RTE', 'carbon'),
8893
'parameter' => __('Maximum number of entries to download', 'carbon'),
8994
];
9095
}
9196
return [];
9297
}
93-
94-
/**
95-
* Automatic action for RTE datasource
96-
*
97-
* @return int
98-
*/
99-
public static function cronDownload(GlpiCronTask $task): int
100-
{
101-
$client = ClientFactory::create(static::$client_name);
102-
return CarbonCronTask::downloadCarbonIntensityFromSource($task, $client, new CarbonIntensity());
103-
}
10498
}

src/Toolbox.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ public static function findTemporalGapsInTable(string $table, DateTimeInterface
634634
// Filter out gaps caused by DST switch
635635
// In the SQL function DATE_ADD() we may do the following process
636636
// DATE_ADD('2022-03-27 01:00:00', INTERVAL 1 HOUR) and '2022-03-27 01:00:00' + INTERVAL 1 HOUR
637-
// while we use Europe/Paris timezone
637+
// while we use Europe/Paris timezone (or any timezone usinf DST)
638638
// Both expressions return '2022-03-27 02:00:00' and it matches the exact time where we switch to summer time
639639
// '2022-03-27 02:00:00' should be actually '2022-03-27 03:00:00', but this is not what happens with MySQL 8.0
640640
// Therefore when the date '2022-03-27 02:00:00' is converted into a DateTime object in PHP with Europe/Paris timezone

tests/install/PluginInstallTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,14 @@ private function checkAutomaticAction()
257257
$cronTask = new GLPICronTask();
258258
$cronTask->getFromDBByCrit([
259259
'itemtype' => RteCronTask::class,
260-
'name' => 'Download',
260+
'name' => 'DownloadRte',
261261
]);
262262
$this->assertFalse($cronTask->isNewItem());
263263

264264
$cronTask = new GLPICronTask();
265265
$cronTask->getFromDBByCrit([
266266
'itemtype' => ElectricityMapsCronTask::class,
267-
'name' => 'Download',
267+
'name' => 'DownloadElectricityMaps',
268268
]);
269269
$this->assertFalse($cronTask->isNewItem());
270270

0 commit comments

Comments
 (0)