diff --git a/app/Services/Binaries/BinaryHandler.php b/app/Services/Binaries/BinaryHandler.php index a8e3d6932..27165a3d5 100644 --- a/app/Services/Binaries/BinaryHandler.php +++ b/app/Services/Binaries/BinaryHandler.php @@ -139,14 +139,22 @@ final class BinaryHandler } try { - $idsByKey = $this->bulkInsertAndResolve($pending); + $result = $this->bulkInsertAndResolve($pending); + $idsByKey = $result['ids']; + $existingKeys = $result['existing']; + $driver = DB::getDriverName(); foreach ($pending as $articleKey => $row) { - $binaryId = $idsByKey[$this->binaryLookupKey($row['hash'], (int) $row['collections_id'])] ?? 0; + $lookupKey = $this->binaryLookupKey($row['hash'], (int) $row['collections_id']); + $binaryId = $idsByKey[$lookupKey] ?? 0; if ($binaryId <= 0) { continue; } $this->binariesUpdate[$binaryId] = $this->binariesUpdate[$binaryId] ?? ['Size' => 0, 'Parts' => 0]; + if ($driver === 'sqlite' && isset($existingKeys[$lookupKey])) { + $this->binariesUpdate[$binaryId]['Size'] += (int) $row['partsize']; + $this->binariesUpdate[$binaryId]['Parts']++; + } if (isset($extraUpdatesByArticleKey[$articleKey])) { $this->binariesUpdate[$binaryId]['Size'] += $extraUpdatesByArticleKey[$articleKey]['Size']; $this->binariesUpdate[$binaryId]['Parts'] += $extraUpdatesByArticleKey[$articleKey]['Parts']; @@ -172,7 +180,7 @@ final class BinaryHandler /** * @param array> $rowsByArticleKey - * @return array Binary ids keyed by hash:collectionId + * @return array{ids: array, existing: array} */ private function bulkInsertAndResolve(array $rowsByArticleKey): array { @@ -192,7 +200,7 @@ final class BinaryHandler } } - return $idsByKey; + return ['ids' => $idsByKey, 'existing' => $existingKeys]; } /** diff --git a/tests/Feature/BinariesStorageInternalsTest.php b/tests/Feature/BinariesStorageInternalsTest.php index 5e317414d..a3779090b 100644 --- a/tests/Feature/BinariesStorageInternalsTest.php +++ b/tests/Feature/BinariesStorageInternalsTest.php @@ -165,6 +165,28 @@ class BinariesStorageInternalsTest extends TestCase $this->assertSame(325, (int) $binary->partsize); } + public function test_header_storage_batch_updates_binary_that_exists_before_chunk(): void + { + $this->createHeaderStorageTables(); + + $service = new HeaderStorageService($this->deterministicCollectionHandler(), config: new BinariesConfig(partsChunkSize: 10)); + $this->assertSame([], $service->store([ + $this->parsedHeader(501, 1, 'Existing.Batch.Release', 100), + ], ['id' => 1, 'name' => 'alt.test'], true)); + + $this->assertSame([], $service->store([ + $this->parsedHeader(502, 2, 'Existing.Batch.Release', 150), + ], ['id' => 1, 'name' => 'alt.test'], true)); + + $binary = DB::table('binaries')->first(); + + $this->assertSame(1, DB::table('collections')->count()); + $this->assertSame(1, DB::table('binaries')->count()); + $this->assertSame(2, DB::table('parts')->count()); + $this->assertSame(2, (int) $binary->currentparts); + $this->assertSame(250, (int) $binary->partsize); + } + private function rawHeader(int $number, string $subject): array { return [