Skip to content
This repository was archived by the owner on Aug 9, 2021. It is now read-only.

Commit d968de6

Browse files
committed
fix(invitation): add locks to protect concurrent rules edition
The purpose is to avoid simultaneous modification of rules in some specific cases Signed-off-by: Thierry Bugier <[email protected]>
1 parent 2f260f0 commit d968de6

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
namespace GlpiPlugin\Flyvemdm\Exception;
4+
5+
6+
class EntityRuleEditionException extends \Exception {}

inc/fusioninventory.class.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
* ------------------------------------------------------------------------------
3030
*/
3131

32-
use GlpiPlugin\Flyvemdm\Exception\FusionInventoryRuleInconsistency;
32+
use GlpiPlugin\Flyvemdm\Exception\FusionInventoryRuleInconsistency;
33+
use GlpiPlugin\Flyvemdm\Exception\EntityRuleEditionException;
3334

3435
if (!defined('GLPI_ROOT')) {
3536
die("Sorry. You can't access this file directly");
@@ -39,6 +40,9 @@ class PluginFlyvemdmFusionInventory {
3940

4041
const RULE_NAME = 'Flyve MDM invitation to entity';
4142

43+
const LOCK_NAME = 'flyvemdm_entityRule';
44+
45+
4246
/**
4347
* Creates or updates an entity rule
4448
*
@@ -52,6 +56,10 @@ public function addInvitationRule(PluginFlyvemdmInvitation $invitation) {
5256
Session::addMessageAfterRedirect(__('Unable to get rule for entity', 'flyvemdm'),
5357
true, ERROR);
5458
return;
59+
} catch (EntityRuleEditionException $exception) {
60+
Session::addMessageAfterRedirect(__('Cannot get lock for entity rules edition', 'flyvemdm'),
61+
true, ERROR);
62+
return;
5563
}
5664

5765
$ruleCriteria = new RuleCriteria();
@@ -117,6 +125,19 @@ public function deleteInvitationRuleCriteria(PluginFlyvemdmInvitation $invitatio
117125
]);
118126

119127
$ruleId = $row[$ruleFk];
128+
129+
// get a lock
130+
$attempts = 0;
131+
$locked = 0;
132+
do {
133+
$locked = $DB->getLock(self::LOCK_NAME);
134+
usleep(50000); // 50 milliseconds
135+
$attempts++;
136+
} while ($locked !== 1 && $attempts < 10);
137+
if ($locked !== 1) {
138+
return; // No lock, then give up disabling
139+
}
140+
120141
$rows = $ruleCriteria->find("`$ruleFk` = '$ruleId' AND `criteria` = 'tag' AND `condition` = '0'");
121142
if (count($rows) === 0) {
122143
$rule = new PluginFusioninventoryInventoryRuleEntity();
@@ -125,6 +146,7 @@ public function deleteInvitationRuleCriteria(PluginFlyvemdmInvitation $invitatio
125146
'is_active' => '0',
126147
]);
127148
}
149+
$DB->releaseLock(self::LOCK_NAME);
128150
}
129151

130152
/**
@@ -144,10 +166,23 @@ private function getRuleCriteriaValue(PluginFlyvemdmInvitation $invitation) {
144166
*
145167
* @return PluginFusioninventoryInventoryRuleEntity|null
146168
* @throws FusionInventoryRuleInconsistency
169+
* @throws EntityRuleEditionException
147170
*/
148171
private function getRule($entityId, $create = true) {
149172
global $DB;
150173

174+
// get a lock
175+
$attempts = 0;
176+
$locked = 0;
177+
do {
178+
$locked = $DB->getLock(self::LOCK_NAME);
179+
usleep(50000); // 50 milliseconds
180+
$attempts++;
181+
} while ($locked !== 1 && $attempts < 10);
182+
if ($locked !== 1) {
183+
throw new EntityRuleEditionException(__('Cannot get lock for entity rules edition'));
184+
}
185+
151186
$ruleEntityTable = PluginFusioninventoryInventoryRuleEntity::getTable();
152187
$ruleActionTable = RuleAction::getTable();
153188
$request = [
@@ -175,13 +210,16 @@ private function getRule($entityId, $create = true) {
175210
$rule = new PluginFusioninventoryInventoryRuleEntity();
176211
$row = $result->next();
177212
$rule->getFromDB($row['id']);
213+
$DB->releaseLock(self::LOCK_NAME);
178214
return $rule;
179215
}
180216
if ($result->count() > 1) {
217+
$DB->releaseLock(self::LOCK_NAME);
181218
throw new FusionInventoryRuleInconsistency(__('Import rule is not unique'));
182219
}
183220

184221
if (!$create) {
222+
$DB->releaseLock(self::LOCK_NAME);
185223
return null;
186224
}
187225

@@ -203,6 +241,7 @@ private function getRule($entityId, $create = true) {
203241
'field' => Entity::getForeignKeyField(),
204242
'value' => $entityId,
205243
]);
244+
$DB->releaseLock(self::LOCK_NAME);
206245
return $rule;
207246
}
208247
}

0 commit comments

Comments
 (0)