Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Aubry <matt@piwik.org>2015-03-13 05:24:12 +0300
committerMatthieu Aubry <matt@piwik.org>2015-03-13 05:24:12 +0300
commitac8793318daa2fc009439a5918ae9129c1dfd472 (patch)
tree51a339b55ac9bfd0ff72279df48992a14306dc1b /plugins
parentf95d109fb120c97828a5a908a88075e97d3f8b2e (diff)
parentf19f7fe42fbd129e7b28813c4dd110d9d0e8b558 (diff)
Merge pull request #7377 from piwik/7181_isolated_archive_purging
refactor archive purging for clarity and resilience.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/CoreAdminHome/API.php2
-rw-r--r--plugins/CoreAdminHome/Commands/FixDuplicateLogActions.php2
-rw-r--r--plugins/CoreAdminHome/Commands/PurgeOldArchiveData.php180
-rw-r--r--plugins/CoreAdminHome/Tasks.php63
-rw-r--r--plugins/CoreAdminHome/Tasks/ArchivesToPurgeDistributedList.php64
-rw-r--r--plugins/CoreAdminHome/tests/Integration/Commands/PurgeOldArchiveDataTest.php152
-rw-r--r--plugins/CoreAdminHome/tests/Integration/TasksTest.php88
-rw-r--r--plugins/SitesManager/SitesManager.php3
-rw-r--r--plugins/SitesManager/tests/Integration/SitesManagerTest.php2
9 files changed, 547 insertions, 9 deletions
diff --git a/plugins/CoreAdminHome/API.php b/plugins/CoreAdminHome/API.php
index 60ba204d45..6329fc8993 100644
--- a/plugins/CoreAdminHome/API.php
+++ b/plugins/CoreAdminHome/API.php
@@ -10,7 +10,7 @@ namespace Piwik\Plugins\CoreAdminHome;
use Exception;
use Piwik\Container\StaticContainer;
-use Piwik\DataAccess\ArchiveInvalidator;
+use Piwik\Archive\ArchiveInvalidator;
use Piwik\Db;
use Piwik\Piwik;
use Piwik\Scheduler\Scheduler;
diff --git a/plugins/CoreAdminHome/Commands/FixDuplicateLogActions.php b/plugins/CoreAdminHome/Commands/FixDuplicateLogActions.php
index 47a058c7ad..be9c74a152 100644
--- a/plugins/CoreAdminHome/Commands/FixDuplicateLogActions.php
+++ b/plugins/CoreAdminHome/Commands/FixDuplicateLogActions.php
@@ -11,7 +11,7 @@ namespace Piwik\Plugins\CoreAdminHome\Commands;
use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\DataAccess\Actions;
-use Piwik\DataAccess\ArchiveInvalidator;
+use Piwik\Archive\ArchiveInvalidator;
use Piwik\Plugin\ConsoleCommand;
use Piwik\Plugins\CoreAdminHome\Model\DuplicateActionRemover;
use Piwik\Timer;
diff --git a/plugins/CoreAdminHome/Commands/PurgeOldArchiveData.php b/plugins/CoreAdminHome/Commands/PurgeOldArchiveData.php
new file mode 100644
index 0000000000..89696eaa9b
--- /dev/null
+++ b/plugins/CoreAdminHome/Commands/PurgeOldArchiveData.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreAdminHome\Commands;
+
+use Piwik\Archive;
+use Piwik\Archive\ArchivePurger;
+use Piwik\DataAccess\ArchiveTableCreator;
+use Piwik\Date;
+use Piwik\Db;
+use Piwik\Plugin\ConsoleCommand;
+use Piwik\Timer;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Command that allows users to force purge old or invalid archive data. In the event of a failure
+ * in the archive purging scheduled task, this command can be used to manually delete old/invalid archives.
+ */
+class PurgeOldArchiveData extends ConsoleCommand
+{
+ const ALL_DATES_STRING = 'all';
+
+ /**
+ * @var ArchivePurger
+ */
+ private $archivePurger;
+
+ /**
+ * For tests.
+ *
+ * @var Date
+ */
+ public static $todayOverride = null;
+
+ public function __construct(ArchivePurger $archivePurger = null)
+ {
+ parent::__construct();
+
+ $this->archivePurger = $archivePurger ?: new ArchivePurger();
+ }
+
+ protected function configure()
+ {
+ $this->setName('core:purge-old-archive-data');
+ $this->setDescription('Purges out of date and invalid archive data from archive tables.');
+ $this->addArgument("dates", InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
+ "The months of the archive tables to purge data from. By default, only deletes from the current month. Use '" . self::ALL_DATES_STRING. "' for all dates.",
+ array(self::getToday()->toString()));
+ $this->addOption('exclude-outdated', null, InputOption::VALUE_NONE, "Do not purge outdated archive data.");
+ $this->addOption('exclude-invalidated', null, InputOption::VALUE_NONE, "Do not purge invalidated archive data.");
+ $this->addOption('exclude-ranges', null, InputOption::VALUE_NONE, "Do not purge custom ranges.");
+ $this->addOption('skip-optimize-tables', null, InputOption::VALUE_NONE, "Do not run OPTIMIZE TABLES query on affected archive tables.");
+ $this->setHelp("By default old and invalidated archives are purged. Custom ranges are also purged with outdated archives.\n\n"
+ . "Note: archive purging is done during scheduled task execution, so under normal circumstances, you should not need to "
+ . "run this command manually.");
+
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $archivePurger = $this->archivePurger;
+
+ $dates = $this->getDatesToPurgeFor($input);
+
+ $excludeOutdated = $input->getOption('exclude-outdated');
+ if ($excludeOutdated) {
+ $output->writeln("Skipping purge outdated archive data.");
+ } else {
+ foreach ($dates as $date) {
+ $message = sprintf("Purging outdated archives for %s...", $date->toString('Y_m'));
+ $this->performTimedPurging($output, $message, function () use ($date, $archivePurger) {
+ $archivePurger->purgeOutdatedArchives($date);
+ });
+ }
+ }
+
+ $excludeInvalidated = $input->getOption('exclude-invalidated');
+ if ($excludeInvalidated) {
+ $output->writeln("Skipping purge invalidated archive data.");
+ } else {
+ foreach ($dates as $date) {
+ $message = sprintf("Purging invalidated archives for %s...", $date->toString('Y_m'));
+ $this->performTimedPurging($output, $message, function () use ($archivePurger, $date) {
+ $archivePurger->purgeInvalidatedArchivesFrom($date);
+ });
+ }
+ }
+
+ $excludeCustomRanges = $input->getOption('exclude-ranges');
+ if ($excludeCustomRanges) {
+ $output->writeln("Skipping purge custom range archives.");
+ } else {
+ foreach ($dates as $date) {
+ $message = sprintf("Purging custom range archives for %s...", $date->toString('Y_m'));
+ $this->performTimedPurging($output, $message, function () use ($date, $archivePurger) {
+ $archivePurger->purgeArchivesWithPeriodRange($date);
+ });
+ }
+ }
+
+ $skipOptimizeTables = $input->getOption('skip-optimize-tables');
+ if ($skipOptimizeTables) {
+ $output->writeln("Skipping OPTIMIZE TABLES.");
+ } else {
+ $this->optimizeArchiveTables($output, $dates);
+ }
+ }
+
+ /**
+ * @param InputInterface $input
+ * @return Date[]
+ */
+ private function getDatesToPurgeFor(InputInterface $input)
+ {
+ $dates = array();
+
+ $dateSpecifier = $input->getArgument('dates');
+ if (count($dateSpecifier) === 1
+ && reset($dateSpecifier) == self::ALL_DATES_STRING
+ ) {
+ foreach (ArchiveTableCreator::getTablesArchivesInstalled() as $table) {
+ $tableDate = ArchiveTableCreator::getDateFromTableName($table);
+
+ list($year, $month) = explode('_', $tableDate);
+
+ $dates[] = Date::factory($year . '-' . $month . '-' . '01');
+ }
+ } else {
+ foreach ($dateSpecifier as $date) {
+ $dates[] = Date::factory($date);
+ }
+ }
+
+ return $dates;
+ }
+
+ private function performTimedPurging(OutputInterface $output, $startMessage, $callback)
+ {
+ $timer = new Timer();
+
+ $output->write($startMessage);
+
+ $callback();
+
+ $output->writeln("Done. <comment>[" . $timer->__toString() . "]</comment>");
+ }
+
+ /**
+ * @param Date[] $dates
+ */
+ private function optimizeArchiveTables(OutputInterface $output, $dates)
+ {
+ $output->writeln("Optimizing archive tables...");
+
+ foreach ($dates as $date) {
+ $numericTable = ArchiveTableCreator::getNumericTable($date);
+ $this->performTimedPurging($output, "Optimizing table $numericTable...", function () use ($numericTable) {
+ Db::optimizeTables($numericTable);
+ });
+
+ $blobTable = ArchiveTableCreator::getBlobTable($date);
+ $this->performTimedPurging($output, "Optimizing table $blobTable...", function () use ($blobTable) {
+ Db::optimizeTables($blobTable);
+ });
+ }
+ }
+
+ private static function getToday()
+ {
+ return self::$todayOverride ?: Date::today();
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/Tasks.php b/plugins/CoreAdminHome/Tasks.php
index d633b9fd5d..700c7d69c2 100644
--- a/plugins/CoreAdminHome/Tasks.php
+++ b/plugins/CoreAdminHome/Tasks.php
@@ -8,13 +8,28 @@
*/
namespace Piwik\Plugins\CoreAdminHome;
-use Piwik\DataAccess\ArchivePurger;
+use Piwik\ArchiveProcessor\Rules;
+use Piwik\Archive\ArchivePurger;
+use Piwik\Container\StaticContainer;
use Piwik\DataAccess\ArchiveTableCreator;
use Piwik\Date;
use Piwik\Db;
+use Piwik\Log;
+use Piwik\Plugins\CoreAdminHome\Tasks\ArchivesToPurgeDistributedList;
+use Piwik\SettingsServer;
class Tasks extends \Piwik\Plugin\Tasks
{
+ /**
+ * @var ArchivePurger
+ */
+ private $archivePurger;
+
+ public function __construct(ArchivePurger $archivePurger = null)
+ {
+ $this->archivePurger = $archivePurger ?: new ArchivePurger();
+ }
+
public function schedule()
{
// general data purge on older archive tables, executed daily
@@ -29,21 +44,47 @@ class Tasks extends \Piwik\Plugin\Tasks
public function purgeOutdatedArchives()
{
+ $logger = StaticContainer::get('Psr\Log\LoggerInterface');
+
+ if ($this->willPurgingCausePotentialProblemInUI()) {
+ $logger->info("Purging temporary archives: skipped (browser triggered archiving not enabled & not running after core:archive)");
+ return false;
+ }
+
$archiveTables = ArchiveTableCreator::getTablesArchivesInstalled();
+
+ $logger->info("Purging archives in {tableCount} archive tables.", array('tableCount' => count($archiveTables)));
+
+ // keep track of dates we purge for, since getTablesArchivesInstalled() will return numeric & blob
+ // tables (so dates will appear two times, and we should only purge once per date)
+ $datesPurged = array();
+
foreach ($archiveTables as $table) {
$date = ArchiveTableCreator::getDateFromTableName($table);
list($year, $month) = explode('_', $date);
// Somehow we may have archive tables created with older dates, prevent exception from being thrown
- if ($year > 1990) {
- ArchivePurger::purgeOutdatedArchives(Date::factory("$year-$month-15"));
+ if ($year > 1990
+ && empty($datesPurged[$date])
+ ) {
+ $dateObj = Date::factory("$year-$month-15");
+
+ $this->archivePurger->purgeOutdatedArchives($dateObj);
+ $this->archivePurger->purgeArchivesWithPeriodRange($dateObj);
+
+ $datesPurged[$date] = true;
}
}
}
public function purgeInvalidatedArchives()
{
- ArchivePurger::purgeInvalidatedArchives();
+ $archivesToPurge = new ArchivesToPurgeDistributedList();
+ foreach ($archivesToPurge->getAllAsDates() as $date) {
+ $this->archivePurger->purgeInvalidatedArchivesFrom($date);
+
+ $archivesToPurge->removeDate($date);
+ }
}
public function optimizeArchiveTable()
@@ -51,4 +92,18 @@ class Tasks extends \Piwik\Plugin\Tasks
$archiveTables = ArchiveTableCreator::getTablesArchivesInstalled();
Db::optimizeTables($archiveTables);
}
+
+ /**
+ * we should only purge outdated & custom range archives if we know cron archiving has just run,
+ * or if browser triggered archiving is enabled. if cron archiving has run, then we know the latest
+ * archives are in the database, and we can remove temporary ones. if browser triggered archiving is
+ * enabled, then we know any archives that are wrongly purged, can be re-archived on demand.
+ * this prevents some situations where "no data" is displayed for reports that should have data.
+ *
+ * @return bool
+ */
+ private function willPurgingCausePotentialProblemInUI()
+ {
+ return !Rules::isRequestAuthorizedToArchive();
+ }
} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/Tasks/ArchivesToPurgeDistributedList.php b/plugins/CoreAdminHome/Tasks/ArchivesToPurgeDistributedList.php
new file mode 100644
index 0000000000..6d56286632
--- /dev/null
+++ b/plugins/CoreAdminHome/Tasks/ArchivesToPurgeDistributedList.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\CoreAdminHome\Tasks;
+
+use Piwik\Concurrency\DistributedList;
+use Piwik\Date;
+
+/**
+ * Distributed list that holds a list of year-month archive table identifiers (eg, 2015_01 or 2014_11). Each item in the
+ * list is expected to identify a pair of archive tables that contain invalidated archives.
+ *
+ * The archiving purging scheduled task will read items in this list when executing the daily purge.
+ *
+ * This class is necessary in order to keep the archive purging scheduled task fast. W/o a way to keep track of
+ * tables w/ invalid data, the task would have to iterate over every table, which is not desired for a task that
+ * is executed daily.
+ *
+ * If users find other tables contain invalidated archives, they can use the core:purge-old-archive-data command
+ * to manually purge them.
+ */
+class ArchivesToPurgeDistributedList extends DistributedList
+{
+ const OPTION_INVALIDATED_DATES_SITES_TO_PURGE = 'InvalidatedOldReports_DatesWebsiteIds';
+
+ public function __construct()
+ {
+ parent::__construct(self::OPTION_INVALIDATED_DATES_SITES_TO_PURGE);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setAll($yearMonths)
+ {
+ $yearMonths = array_unique($yearMonths);
+ parent::setAll($yearMonths);
+ }
+
+ public function getAllAsDates()
+ {
+ $dates = array();
+ foreach ($this->getAll() as $yearMonth) {
+ try {
+ $date = Date::factory(str_replace('_', '-', $yearMonth) . '-01');
+ } catch (\Exception $ex) {
+ continue; // invalid year month in distributed list
+ }
+
+ $dates[] = $date;
+ }
+ return $dates;
+ }
+
+ public function removeDate(Date $date)
+ {
+ $yearMonth = $date->toString('Y_m');
+ $this->remove($yearMonth);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/tests/Integration/Commands/PurgeOldArchiveDataTest.php b/plugins/CoreAdminHome/tests/Integration/Commands/PurgeOldArchiveDataTest.php
new file mode 100644
index 0000000000..ecb07aa438
--- /dev/null
+++ b/plugins/CoreAdminHome/tests/Integration/Commands/PurgeOldArchiveDataTest.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\CoreAdminHome\tests\Integration\Commands;
+
+use Piwik\Archive\ArchivePurger;
+use Piwik\Console;
+use Piwik\Date;
+use Piwik\Plugins\CoreAdminHome\Commands\PurgeOldArchiveData;
+use Piwik\Tests\Fixtures\RawArchiveDataWithTempAndInvalidated;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Symfony\Component\Console\Tester\ApplicationTester;
+
+/**
+ * @group Core
+ */
+class PurgeOldArchiveDataTest extends IntegrationTestCase
+{
+ /**
+ * @var RawArchiveDataWithTempAndInvalidated
+ */
+ public static $fixture = null;
+
+ /**
+ * @var ApplicationTester
+ */
+ protected $applicationTester = null;
+
+ /**
+ * @var Console
+ */
+ protected $application;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ PurgeOldArchiveData::$todayOverride = Date::factory('2015-02-27');
+
+ $archivePurger = new ArchivePurger();
+ $archivePurger->setTodayDate(Date::factory('2015-02-27'));
+ $archivePurger->setYesterdayDate(Date::factory('2015-02-26'));
+ $archivePurger->setNow(Date::factory('2015-02-27 08:00:00')->getTimestamp());
+
+ $this->application = new Console();
+ $this->application->setAutoExit(false);
+ $this->application->add(new PurgeOldArchiveData($archivePurger));
+
+ $this->applicationTester = new ApplicationTester($this->application);
+
+ // assert the test data was setup correctly
+ self::$fixture->assertInvalidatedArchivesNotPurged(self::$fixture->january);
+ self::$fixture->assertInvalidatedArchivesNotPurged(self::$fixture->february);
+ }
+
+ public function tearDown()
+ {
+ PurgeOldArchiveData::$todayOverride = null;
+
+ parent::tearDown();
+ }
+
+ public function test_ExecutingCommandWithAllDates_PurgesAllExistingArchiveTables()
+ {
+ $result = $this->applicationTester->run(array(
+ 'command' => 'core:purge-old-archive-data',
+ 'dates' => array('all'),
+ '-vvv' => true
+ ));
+
+ $this->assertEquals(0, $result, $this->getCommandDisplayOutputErrorMessage());
+
+ self::$fixture->assertInvalidatedArchivesPurged(self::$fixture->february);
+ self::$fixture->assertTemporaryArchivesPurged($isBrowserTriggeredArchivingEnabled = true, self::$fixture->february);
+ self::$fixture->assertCustomRangesPurged(self::$fixture->february);
+
+ self::$fixture->assertInvalidatedArchivesPurged(self::$fixture->january);
+ self::$fixture->assertTemporaryArchivesPurged($isBrowserTriggeredArchivingEnabled = true, self::$fixture->january);
+ self::$fixture->assertCustomRangesPurged(self::$fixture->january);
+ }
+
+ public function test_ExecutingCommandWithNoDate_PurgesArchiveTableForToday()
+ {
+ $result = $this->applicationTester->run(array(
+ 'command' => 'core:purge-old-archive-data',
+ '-vvv' => true
+ ));
+
+ $this->assertEquals(0, $result, $this->getCommandDisplayOutputErrorMessage());
+
+ self::$fixture->assertInvalidatedArchivesPurged(self::$fixture->february);
+ self::$fixture->assertTemporaryArchivesPurged($isBrowserTriggeredArchivingEnabled = true, self::$fixture->february);
+ self::$fixture->assertCustomRangesPurged(self::$fixture->february);
+
+ self::$fixture->assertInvalidatedArchivesNotPurged(self::$fixture->january);
+ self::$fixture->assertTemporaryArchivesNotPurged(self::$fixture->january);
+ self::$fixture->assertCustomRangesNotPurged(self::$fixture->january);
+ }
+
+ public function test_ExecutingCommandWithSpecificDate_PurgesArchiveTableForDate()
+ {
+ $result = $this->applicationTester->run(array(
+ 'command' => 'core:purge-old-archive-data',
+ 'dates' => array('2015-01-14'),
+ '-vvv' => true
+ ));
+
+ $this->assertEquals(0, $result, $this->getCommandDisplayOutputErrorMessage());
+
+ self::$fixture->assertInvalidatedArchivesPurged(self::$fixture->january);
+ self::$fixture->assertTemporaryArchivesPurged($isBrowserTriggeredArchivingEnabled = true, self::$fixture->january);
+ self::$fixture->assertCustomRangesPurged(self::$fixture->january);
+
+ self::$fixture->assertInvalidatedArchivesNotPurged(self::$fixture->february);
+ self::$fixture->assertTemporaryArchivesNotPurged(self::$fixture->february);
+ self::$fixture->assertCustomRangesNotPurged(self::$fixture->february);
+ }
+
+ public function test_ExecutingCommandWithExcludeOptions_SkipsAppropriatePurging()
+ {
+ $result = $this->applicationTester->run(array(
+ 'command' => 'core:purge-old-archive-data',
+ 'dates' => array('2015-01-14'),
+ '--exclude-outdated' => true,
+ '--exclude-invalidated' => true,
+ '--exclude-ranges' => true,
+ '--skip-optimize-tables' => true,
+ '-vvv' => true
+ ));
+
+ $this->assertEquals(0, $result, $this->getCommandDisplayOutputErrorMessage());
+
+ self::$fixture->assertInvalidatedArchivesNotPurged(self::$fixture->january);
+ self::$fixture->assertTemporaryArchivesNotPurged(self::$fixture->january);
+ self::$fixture->assertCustomRangesNotPurged(self::$fixture->january);
+
+ $this->assertContains("Skipping purge outdated archive data.", $this->applicationTester->getDisplay());
+ $this->assertContains("Skipping purge invalidated archive data.", $this->applicationTester->getDisplay());
+ $this->assertContains("Skipping OPTIMIZE TABLES.", $this->applicationTester->getDisplay());
+ }
+
+ protected function getCommandDisplayOutputErrorMessage()
+ {
+ return "Command did not behave as expected. Command output: " . $this->applicationTester->getDisplay();
+ }
+}
+
+PurgeOldArchiveDataTest::$fixture = new RawArchiveDataWithTempAndInvalidated(); \ No newline at end of file
diff --git a/plugins/CoreAdminHome/tests/Integration/TasksTest.php b/plugins/CoreAdminHome/tests/Integration/TasksTest.php
new file mode 100644
index 0000000000..da3800e9c1
--- /dev/null
+++ b/plugins/CoreAdminHome/tests/Integration/TasksTest.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\CoreAdminHome\tests\Integration;
+
+use Piwik\Archive\ArchivePurger;
+use Piwik\Date;
+use Piwik\Plugins\CoreAdminHome\Tasks;
+use Piwik\Plugins\CoreAdminHome\Tasks\ArchivesToPurgeDistributedList;
+use Piwik\Tests\Fixtures\RawArchiveDataWithTempAndInvalidated;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+
+/**
+ * @group Core
+ */
+class TasksTest extends IntegrationTestCase
+{
+ /**
+ * @var RawArchiveDataWithTempAndInvalidated
+ */
+ public static $fixture;
+
+ /**
+ * @var Tasks
+ */
+ private $tasks;
+
+ /**
+ * @var Date
+ */
+ private $january;
+
+ /**
+ * @var Date
+ */
+ private $february;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->january = Date::factory('2015-01-01');
+ $this->february = Date::factory('2015-02-01');
+
+ $archivePurger = new ArchivePurger();
+ $archivePurger->setTodayDate(Date::factory('2015-02-27'));
+ $archivePurger->setYesterdayDate(Date::factory('2015-02-26'));
+ $archivePurger->setNow(Date::factory('2015-02-27 08:00:00')->getTimestamp());
+
+ $this->tasks = new Tasks($archivePurger);
+ }
+
+ public function test_purgeInvalidatedArchives_PurgesCorrectInvalidatedArchives_AndOnlyPurgesDataForDatesAndSites_InInvalidatedReportsDistributedList()
+ {
+ $this->setUpInvalidatedReportsDistributedList($dates = array($this->february));
+
+ $this->tasks->purgeInvalidatedArchives();
+
+ self::$fixture->assertInvalidatedArchivesPurged($this->february);
+ self::$fixture->assertInvalidatedArchivesNotPurged($this->january);
+
+ // assert invalidated reports distributed list has changed
+ $archivesToPurgeDistributedList = new ArchivesToPurgeDistributedList();
+ $yearMonths = $archivesToPurgeDistributedList->getAll();
+
+ $this->assertEmpty($yearMonths);
+ }
+
+ /**
+ * @param Date[] $dates
+ */
+ private function setUpInvalidatedReportsDistributedList($dates)
+ {
+ $yearMonths = array();
+ foreach ($dates as $date) {
+ $yearMonths[] = $date->toString('Y_m');
+ }
+
+ $archivesToPurgeDistributedList = new ArchivesToPurgeDistributedList();
+ $archivesToPurgeDistributedList->add($yearMonths);
+ }
+}
+
+TasksTest::$fixture = new RawArchiveDataWithTempAndInvalidated(); \ No newline at end of file
diff --git a/plugins/SitesManager/SitesManager.php b/plugins/SitesManager/SitesManager.php
index b9c5fa0736..93e1d8c2e8 100644
--- a/plugins/SitesManager/SitesManager.php
+++ b/plugins/SitesManager/SitesManager.php
@@ -9,8 +9,7 @@
namespace Piwik\Plugins\SitesManager;
use Piwik\Common;
-use Piwik\DataAccess\ArchiveInvalidator;
-use Piwik\Db;
+use Piwik\Archive\ArchiveInvalidator;
use Piwik\Tracker\Cache;
use Piwik\Tracker\Model as TrackerModel;
diff --git a/plugins/SitesManager/tests/Integration/SitesManagerTest.php b/plugins/SitesManager/tests/Integration/SitesManagerTest.php
index 135f505f01..1ba60ce972 100644
--- a/plugins/SitesManager/tests/Integration/SitesManagerTest.php
+++ b/plugins/SitesManager/tests/Integration/SitesManagerTest.php
@@ -10,7 +10,7 @@ namespace Piwik\Plugins\SitesManager\tests\Integration;
use Piwik\Access;
use Piwik\Cache;
-use Piwik\DataAccess\ArchiveInvalidator;
+use Piwik\Archive\ArchiveInvalidator;
use Piwik\Date;
use Piwik\Plugins\SitesManager\SitesManager;
use Piwik\Tests\Framework\Fixture;