mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
Optimize binaries insert
This commit is contained in:
@@ -116,10 +116,15 @@ final class BinaryHandler
|
||||
int $fileNumber,
|
||||
int $partSize
|
||||
): int {
|
||||
$affected = DB::affectingStatement(
|
||||
'INSERT OR IGNORE INTO binaries (binaryhash, name, collections_id, totalparts, currentparts, filenumber, partsize) VALUES (?, ?, ?, ?, 1, ?, ?)',
|
||||
[$hash, $name, $collectionId, $totalParts, $fileNumber, $partSize]
|
||||
);
|
||||
$affected = DB::table('binaries')->insertOrIgnore([
|
||||
'binaryhash' => $hash,
|
||||
'name' => $name,
|
||||
'collections_id' => $collectionId,
|
||||
'totalparts' => $totalParts,
|
||||
'currentparts' => 1,
|
||||
'filenumber' => $fileNumber,
|
||||
'partsize' => $partSize,
|
||||
]);
|
||||
|
||||
if ($affected > 0 && ($lastId = (int) DB::connection()->getPdo()->lastInsertId()) > 0) {
|
||||
$this->insertedBinaryIds[$lastId] = true;
|
||||
@@ -214,33 +219,21 @@ final class BinaryHandler
|
||||
private function flushUpdatesMysql(array $updates, int $chunkSize): bool
|
||||
{
|
||||
foreach (array_chunk($updates, $chunkSize) as $chunk) {
|
||||
// Build a CASE statement for batch UPDATE instead of INSERT...ON DUPLICATE KEY
|
||||
// This avoids FK constraint violations when collections have been deleted
|
||||
$ids = [];
|
||||
$partsizeCases = [];
|
||||
$currentpartsCases = [];
|
||||
$selects = [];
|
||||
$bindings = [];
|
||||
|
||||
foreach ($chunk as $row) {
|
||||
$ids[] = $row['id'];
|
||||
$partsizeCases[] = 'WHEN id = ? THEN partsize + ?';
|
||||
$currentpartsCases[] = 'WHEN id = ? THEN currentparts + ?';
|
||||
$selects[] = 'SELECT ? AS id, ? AS partsize, ? AS currentparts';
|
||||
$bindings[] = $row['id'];
|
||||
$bindings[] = $row['partsize'];
|
||||
}
|
||||
|
||||
foreach ($chunk as $row) {
|
||||
$bindings[] = $row['id'];
|
||||
$bindings[] = $row['currentparts'];
|
||||
}
|
||||
|
||||
$idPlaceholders = implode(',', array_fill(0, count($ids), '?'));
|
||||
$bindings = array_merge($bindings, $ids);
|
||||
|
||||
$sql = 'UPDATE binaries SET '
|
||||
.'partsize = CASE '.implode(' ', $partsizeCases).' ELSE partsize END, '
|
||||
.'currentparts = CASE '.implode(' ', $currentpartsCases).' ELSE currentparts END '
|
||||
.'WHERE id IN ('.$idPlaceholders.')';
|
||||
$sql = 'UPDATE binaries b INNER JOIN ('
|
||||
.implode(' UNION ALL ', $selects)
|
||||
.') u ON u.id = b.id '
|
||||
.'SET b.partsize = b.partsize + u.partsize, '
|
||||
.'b.currentparts = b.currentparts + u.currentparts';
|
||||
|
||||
DB::statement($sql, $bindings);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,34 @@ class BinariesStorageInternalsTest extends TestCase
|
||||
$this->assertSame(1, DB::table('parts')->count());
|
||||
}
|
||||
|
||||
public function test_binary_handler_flushes_cached_article_aggregate_updates(): void
|
||||
{
|
||||
DB::statement('CREATE TABLE binaries (
|
||||
id INTEGER PRIMARY KEY,
|
||||
binaryhash BLOB,
|
||||
name VARCHAR(255),
|
||||
collections_id INT,
|
||||
totalparts INT,
|
||||
currentparts INT,
|
||||
filenumber INT,
|
||||
partsize INT,
|
||||
UNIQUE(binaryhash, collections_id)
|
||||
)');
|
||||
|
||||
$handler = new BinaryHandler;
|
||||
$first = $this->parsedHeader(251, 1, 'Aggregate.Release', 100);
|
||||
$second = $this->parsedHeader(252, 2, 'Aggregate.Release', 50);
|
||||
|
||||
$binaryId = $handler->getOrCreateBinary($first, 1, 1, 0);
|
||||
$this->assertNotNull($binaryId);
|
||||
$this->assertSame($binaryId, $handler->getOrCreateBinary($second, 1, 1, 0));
|
||||
$this->assertTrue($handler->flushUpdates());
|
||||
|
||||
$binary = DB::table('binaries')->where('id', $binaryId)->first();
|
||||
$this->assertSame(2, (int) $binary->currentparts);
|
||||
$this->assertSame(150, (int) $binary->partsize);
|
||||
}
|
||||
|
||||
public function test_sqlite_rollback_cleanup_keeps_unrelated_parts_with_same_article_number(): void
|
||||
{
|
||||
DB::statement('CREATE TABLE collections (id INTEGER PRIMARY KEY, collectionhash VARCHAR(40), noise VARCHAR(64))');
|
||||
@@ -102,7 +130,10 @@ class BinariesStorageInternalsTest extends TestCase
|
||||
|
||||
$collectionHandler = new CollectionHandler(new class extends CollectionsCleaningService
|
||||
{
|
||||
public function __construct() {}
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function collectionsCleaner(string $subject, string $groupName = ''): array
|
||||
{
|
||||
@@ -160,13 +191,13 @@ class BinariesStorageInternalsTest extends TestCase
|
||||
subject VARCHAR(255),
|
||||
fromname VARCHAR(255),
|
||||
date DATETIME NULL,
|
||||
xref TEXT DEFAULT "",
|
||||
xref TEXT DEFAULT \'\',
|
||||
groups_id INT,
|
||||
totalfiles INT,
|
||||
collectionhash VARCHAR(40) UNIQUE,
|
||||
collection_regexes_id INT,
|
||||
dateadded DATETIME NULL,
|
||||
noise VARCHAR(64) DEFAULT ""
|
||||
noise VARCHAR(64) DEFAULT \'\'
|
||||
)');
|
||||
|
||||
DB::statement('CREATE TABLE binaries (
|
||||
|
||||
Reference in New Issue
Block a user