mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
WIP - prepare cron cleanup + first tests
This commit is contained in:
@@ -89,7 +89,9 @@ class DeletionPlanService
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.3.0
|
||||
* @param array $aClasses
|
||||
* @param int $iUnixTimeLimit : max execution time in seconds since Epoch before stopping deletion. by default: no limit (ie remove all without stop)
|
||||
*
|
||||
* @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity>
|
||||
* @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException
|
||||
@@ -97,7 +99,7 @@ class DeletionPlanService
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function ExecuteDeletionPlan(array $aClasses): array
|
||||
public function ExecuteDeletionPlan(array $aClasses, int $iUnixTimeLimit = 0): array
|
||||
{
|
||||
$oDeletionPlan = $this->GetDeletionPlan($aClasses);
|
||||
|
||||
@@ -110,6 +112,11 @@ class DeletionPlanService
|
||||
$oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass);
|
||||
|
||||
foreach ($aToUpdate as $aData) {
|
||||
if ($this->IsTimeLimitExceeded($iUnixTimeLimit)) {
|
||||
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
|
||||
return $aSummary;
|
||||
}
|
||||
|
||||
$oToUpdate = $aData['to_reset'];
|
||||
/** @var \DBObject $oToUpdate */
|
||||
foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) {
|
||||
@@ -126,20 +133,33 @@ class DeletionPlanService
|
||||
$oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass);
|
||||
|
||||
foreach ($aDeletes as $sId => $aDelete) {
|
||||
// Delete any existing change tracking about the current object
|
||||
$oFilter = new DBObjectSearch('CMDBChangeOp');
|
||||
$oFilter->AddCondition('objclass', $sClass, '=');
|
||||
$oFilter->AddCondition('objkey', $sId, '=');
|
||||
MetaModel::PurgeData($oFilter);
|
||||
|
||||
// Delete the entry
|
||||
$aClassesToRemove = array_merge(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL), MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false));
|
||||
foreach ($aClassesToRemove as $sParentClass) {
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id");
|
||||
$sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]);
|
||||
CMDBSource::DeleteFrom($sQuery);
|
||||
if ($this->IsTimeLimitExceeded($iUnixTimeLimit)) {
|
||||
$aSummary[$sClass] = $oDeletionPlanSummaryEntity;
|
||||
return $aSummary;
|
||||
}
|
||||
|
||||
try {
|
||||
CMDBSource::Query('START TRANSACTION');
|
||||
// Delete any existing change tracking about the current object
|
||||
$oFilter = new DBObjectSearch('CMDBChangeOp');
|
||||
$oFilter->AddCondition('objclass', $sClass, '=');
|
||||
$oFilter->AddCondition('objkey', $sId, '=');
|
||||
MetaModel::PurgeData($oFilter);
|
||||
|
||||
// Delete the entry
|
||||
$aClassesToRemove = array_merge(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL), MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false));
|
||||
foreach ($aClassesToRemove as $sParentClass) {
|
||||
$oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id");
|
||||
$sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]);
|
||||
CMDBSource::DeleteFrom($sQuery);
|
||||
}
|
||||
|
||||
CMDBSource::Query('COMMIT');
|
||||
} catch (\Exception $e) {
|
||||
\IssueLog::Exception(__METHOD__.": Cleanup failed", $e);
|
||||
CMDBSource::Query('ROLLBACK');
|
||||
throw $e;
|
||||
}
|
||||
$oDeletionPlanSummaryEntity->iDeleteCount++;
|
||||
}
|
||||
|
||||
@@ -171,4 +191,13 @@ class DeletionPlanService
|
||||
|
||||
return $oDeletionPlan;
|
||||
}
|
||||
|
||||
public function IsTimeLimitExceeded(int $iUnixTimeLimit): bool
|
||||
{
|
||||
if ($iUnixTimeLimit === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (time() <= $iUnixTimeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service\Test;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\DeletionPlanService;
|
||||
use Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase;
|
||||
|
||||
class DeletionPlanServiceTest extends TestCase {
|
||||
class DeletionPlanServiceTest extends ItopCustomDatamodelTestCase
|
||||
{
|
||||
public function testExecuteDeletionPlan_DeleteAllWithoutLimit()
|
||||
{
|
||||
$iDFRToRemoveLeaf = $this->GivenObjectInDB('DFRToRemoveLeaf', ['name' => 'ga']);
|
||||
$this->GivenObjectInDB('DFRToUpdate', ['name' => 'bu', 'dfrtoremove_id' => $iDFRToRemoveLeaf]);
|
||||
$iDFRRemovedCollateral = $this->GivenObjectInDB('DFRRemovedCollateral', ['name' => 'zo', 'dfrtoremove_id' => $iDFRToRemoveLeaf]);
|
||||
$this->GivenObjectInDB('DFRRemovedCollateralCascade', ['name' => 'meu', 'dfrremovedcollateral_id' => $iDFRRemovedCollateral]);
|
||||
|
||||
$aClasses = [ 'DFRToRemoveLeaf' ];
|
||||
$aRes = DeletionPlanService::GetInstance()->ExecuteDeletionPlan($aClasses);
|
||||
$aExpected = [
|
||||
['DFRToUpdate', 1, 0 ],
|
||||
['DFRToRemoveLeaf', 0, 1 ],
|
||||
['DFRRemovedCollateral', 0, 1 ],
|
||||
['DFRRemovedCollateralCascade', 0, 1 ],
|
||||
];
|
||||
$this->AssertSummaryEquals($aExpected, $aRes, 'DeleteAllWithoutLimit');
|
||||
}
|
||||
|
||||
private function AssertSummaryEquals(array $expected, $actual, $sMessage = '')
|
||||
{
|
||||
$aExpected = [];
|
||||
foreach ($expected as $line) {
|
||||
$sClass = $line[0];
|
||||
$iUpdate = $line[1];
|
||||
$iDelete = $line[2];
|
||||
|
||||
$oDeletionPlanSummaryEntity = new DeletionPlanSummaryEntity($sClass);
|
||||
$oDeletionPlanSummaryEntity->iUpdateCount = $iUpdate;
|
||||
$oDeletionPlanSummaryEntity->iDeleteCount = $iDelete;
|
||||
$aExpected[$sClass] = $oDeletionPlanSummaryEntity;
|
||||
}
|
||||
$this->assertEquals($aExpected, $actual, $sMessage);
|
||||
}
|
||||
|
||||
public function testExecuteDeletionPlan_StopInUpdates()
|
||||
{
|
||||
self::markTestSkipped();
|
||||
}
|
||||
|
||||
public function testExecuteDeletionPlan_StopInDeletes()
|
||||
{
|
||||
self::markTestSkipped();
|
||||
}
|
||||
|
||||
public function GetDatamodelDeltaAbsPath(): string
|
||||
{
|
||||
return __DIR__.'/deletionplan_delta.xml';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user