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

Commit bb2f238

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 1ad9846 commit bb2f238

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

inc/fusioninventory.class.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class PluginFlyvemdmFusionInventory {
3939

4040
const RULE_NAME = 'Flyve MDM invitation to entity';
4141

42+
const LOCK_NAME = 'flyvemdm_entityRule';
43+
44+
4245
/**
4346
* Creates or updates an entity rule
4447
*
@@ -52,6 +55,10 @@ public function addInvitationRule(PluginFlyvemdmInvitation $invitation) {
5255
Session::addMessageAfterRedirect(__('Unable to get rule for entity', 'flyvemdm'),
5356
true, ERROR);
5457
return;
58+
} catch (EntityRuleEditionException $exception) {
59+
Session::addMessageAfterRedirect(__('Cannot get lock for entity rules edition', 'flyvemdm'),
60+
true, ERROR);
61+
return;
5562
}
5663

5764
$ruleCriteria = new RuleCriteria();
@@ -117,6 +124,19 @@ public function deleteInvitationRuleCriteria(PluginFlyvemdmInvitation $invitatio
117124
]);
118125

119126
$ruleId = $row[$ruleFk];
127+
128+
// get a lock
129+
$attempts = 0;
130+
$locked = 0;
131+
do {
132+
$locked = $DB->getLock(self::LOCK_NAME);
133+
usleep(50000); // 50 milliseconds
134+
$attempts++;
135+
} while ($locked !== 1 && $attempts < 10);
136+
if ($locked !== 1) {
137+
return; // No lock, then give up disabling
138+
}
139+
120140
$rows = $ruleCriteria->find("`$ruleFk` = '$ruleId' AND `criteria` = 'tag' AND `condition` = '0'");
121141
if (count($rows) === 0) {
122142
$rule = new PluginFusioninventoryInventoryRuleEntity();
@@ -125,6 +145,7 @@ public function deleteInvitationRuleCriteria(PluginFlyvemdmInvitation $invitatio
125145
'is_active' => '0',
126146
]);
127147
}
148+
$DB->releaseLock(self::LOCK_NAME);
128149
}
129150

130151
/**
@@ -144,10 +165,23 @@ private function getRuleCriteriaValue(PluginFlyvemdmInvitation $invitation) {
144165
*
145166
* @return PluginFusioninventoryInventoryRuleEntity|null
146167
* @throws FusionInventoryRuleInconsistency
168+
* @throws EntityRuleEditionException
147169
*/
148170
private function getRule($entityId, $create = true) {
149171
global $DB;
150172

173+
// get a lock
174+
$attempts = 0;
175+
$locked = 0;
176+
do {
177+
$locked = $DB->getLock(self::LOCK_NAME);
178+
usleep(50000); // 50 milliseconds
179+
$attempts++;
180+
} while ($locked !== 1 && $attempts < 10);
181+
if ($locked !== 1) {
182+
throw new EntityRuleEditionException(__('Cannot get lock for entity rules edition'));
183+
}
184+
151185
$ruleEntityTable = PluginFusioninventoryInventoryRuleEntity::getTable();
152186
$ruleActionTable = RuleAction::getTable();
153187
$request = [
@@ -175,13 +209,16 @@ private function getRule($entityId, $create = true) {
175209
$rule = new PluginFusioninventoryInventoryRuleEntity();
176210
$row = $result->next();
177211
$rule->getFromDB($row['id']);
212+
$DB->releaseLock(self::LOCK_NAME);
178213
return $rule;
179214
}
180215
if ($result->count() > 1) {
216+
$DB->releaseLock(self::LOCK_NAME);
181217
throw new FusionInventoryRuleInconsistency(__('Import rule is not unique'));
182218
}
183219

184220
if (!$create) {
221+
$DB->releaseLock(self::LOCK_NAME);
185222
return null;
186223
}
187224

@@ -203,6 +240,7 @@ private function getRule($entityId, $create = true) {
203240
'field' => Entity::getForeignKeyField(),
204241
'value' => $entityId,
205242
]);
243+
$DB->releaseLock(self::LOCK_NAME);
206244
return $rule;
207245
}
208246
}

0 commit comments

Comments
 (0)