1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Basic database maintenance

Closes #169
This commit is contained in:
J. King 2019-07-26 09:37:51 -04:00
parent cef31907d3
commit f7240301e4
10 changed files with 63 additions and 4 deletions

View file

@ -13,6 +13,9 @@ Bug fixes:
- Sort Tiny Tiny RSS special feeds according to special ordering - Sort Tiny Tiny RSS special feeds according to special ordering
- Invalidate sessions when passwords are changed - Invalidate sessions when passwords are changed
Changes:
- Perform regular database maintenance to improve long-term performance
Version 0.7.1 (2019-03-25) Version 0.7.1 (2019-03-25)
========================== ==========================

View file

@ -110,6 +110,11 @@ class Database {
return $this->db->charsetAcceptable(); return $this->db->charsetAcceptable();
} }
/** Performs maintenance on the database to ensure good performance */
public function driverMaintenance(): bool {
return $this->db->maintenance();
}
/** Computes the column and value text of an SQL "SET" clause, validating arbitrary input against a whitelist /** Computes the column and value text of an SQL "SET" clause, validating arbitrary input against a whitelist
* *
* Returns an indexed array containing the clause text, an array of types, and another array of values * Returns an indexed array containing the clause text, an array of types, and another array of values
@ -1788,10 +1793,11 @@ class Database {
$limitUnread = Date::sub(Arsse::$conf->purgeArticlesUnread); $limitUnread = Date::sub(Arsse::$conf->purgeArticlesUnread);
} }
$feeds = $this->db->query("SELECT id, size from arsse_feeds")->getAll(); $feeds = $this->db->query("SELECT id, size from arsse_feeds")->getAll();
$deleted = 0;
foreach ($feeds as $feed) { foreach ($feeds as $feed) {
$query->run($feed['id'], $feed['size'], $feed['id'], $limitUnread, $limitRead); $deleted += $query->run($feed['id'], $feed['size'], $feed['id'], $limitUnread, $limitRead)->changes();
} }
return true; return (bool) $deleted;
} }
/** Ensures the specified article exists and raises an exception otherwise /** Ensures the specified article exists and raises an exception otherwise

View file

@ -82,4 +82,10 @@ interface Driver {
* This functionality should be avoided in favour of using statement parameters whenever possible * This functionality should be avoided in favour of using statement parameters whenever possible
*/ */
public function literalString(string $str): string; public function literalString(string $str): string;
/** Performs implementation-specific database maintenance to ensure good performance
*
* This should be restricted to quick maintenance; in SQLite terms it might include ANALYZE, but not VACUUM
*/
public function maintenance(): bool;
} }

View file

@ -216,4 +216,17 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
public function literalString(string $str): string { public function literalString(string $str): string {
return "'".$this->db->real_escape_string($str)."'"; return "'".$this->db->real_escape_string($str)."'";
} }
public function maintenance(): bool {
// with MySQL each table must be analyzed separately, so we first have to get a list of tables
foreach ($this->query("SHOW TABLES like 'arsse\\_%'") as $table) {
$table = array_pop($table);
if (!preg_match("/^arsse_[a-z_]+$/", $table)) {
// table is not one of ours
continue; // @codeCoverageIgnore
}
$this->query("ANALYZE TABLE $table");
}
return true;
}
} }

View file

@ -225,4 +225,10 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
public function literalString(string $str): string { public function literalString(string $str): string {
return pg_escape_literal($this->db, $str); return pg_escape_literal($this->db, $str);
} }
public function maintenance(): bool {
// analyze the database
$this->exec("ANALYZE");
return true;
}
} }

View file

@ -188,4 +188,10 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
public function literalString(string $str): string { public function literalString(string $str): string {
return "'".\SQLite3::escapeString($str)."'"; return "'".\SQLite3::escapeString($str)."'";
} }
public function maintenance(): bool {
// analyze the database then checkpoint and truncate the write-ahead log
$this->exec("ANALYZE; PRAGMA wal_checkpoint(truncate)");
return true;
}
} }

View file

@ -92,7 +92,12 @@ class Service {
} }
public static function cleanupPost(): bool { public static function cleanupPost(): bool {
// delete old articles, according to configured threasholds // delete old articles, according to configured thresholds
return Arsse::$db->articleCleanup(); $deleted = Arsse::$db->articleCleanup();
// if any articles were deleted, perform database maintenance
if ($deleted) {
Arsse::$db->driverMaintenance();
}
return true;
} }
} }

View file

@ -44,4 +44,8 @@ trait SeriesMiscellany {
public function testCheckCharacterSetAcceptability() { public function testCheckCharacterSetAcceptability() {
$this->assertInternalType("bool", Arsse::$db->driverCharsetAcceptable()); $this->assertInternalType("bool", Arsse::$db->driverCharsetAcceptable());
} }
public function testPerformMaintenance() {
$this->assertTrue(Arsse::$db->driverMaintenance());
}
} }

View file

@ -382,4 +382,9 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
public function testProduceAStringLiteral() { public function testProduceAStringLiteral() {
$this->assertSame("'It''s a string!'", $this->drv->literalString("It's a string!")); $this->assertSame("'It''s a string!'", $this->drv->literalString("It's a string!"));
} }
public function testPerformMaintenance() {
// this performs maintenance in the absence of tables; see BaseUpdate.php for another test with tables
$this->assertTrue($this->drv->maintenance());
}
} }

View file

@ -130,4 +130,9 @@ class BaseUpdate extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertException("updateTooNew", "Db"); $this->assertException("updateTooNew", "Db");
$this->drv->schemaUpdate(-1, $this->base); $this->drv->schemaUpdate(-1, $this->base);
} }
public function testPerformMaintenance() {
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
$this->assertTrue($this->drv->maintenance());
}
} }