testHeaderStorage = new HeaderStorageService(config: $config); $this->testMissedPartHandler = new MissedPartHandler( $config->partRepairLimit, $config->partRepairMaxTries ); } // Expose protected method for direct testing via new service. public function publicStoreHeaders(array $headers): void { if (empty($this->testGroupMySQL)) { $this->testGroupMySQL = ['id' => 1, 'name' => 'alt.test']; } config(['tests.force_simulated_rollback' => false]); // Parse headers first to add 'matches' $parsedHeaders = []; foreach ($headers as $header) { if (preg_match('/^\s*(?!Usenet Index Post)(.+?)\s+\((\d+)\/(\d+)\)/', $header['Subject'], $matches)) { if (stripos($header['Subject'], 'yEnc') === false) { $matches[1] .= ' yEnc'; } $header['matches'] = $matches; $parsedHeaders[] = $header; } } $this->testHeaderStorage->store($parsedHeaders, $this->testGroupMySQL, true); } public function setAddToPartRepair(bool $val): void { // This is now handled by passing parameter to store() } // Simulate scan path minimally to test rollback + part repair queue logic without NNTP. public function simulateScan(array $headers, array $group, bool $enablePartRepair = true): void { $this->testGroupMySQL = $group; // Parse headers first to add 'matches' $parsedHeaders = []; $headersReceived = []; foreach ($headers as $header) { if (isset($header['Number'])) { $headersReceived[] = $header['Number']; } if (preg_match('/^\s*(?!Usenet Index Post)(.+?)\s+\((\d+)\/(\d+)\)/', $header['Subject'], $matches)) { if (stripos($header['Subject'], 'yEnc') === false) { $matches[1] .= ' yEnc'; } $header['matches'] = $matches; $parsedHeaders[] = $header; } } // If we are simulating a failure, do not perform any inserts; just mark all as missed. if ($this->failPartsInsert) { if ($enablePartRepair) { $this->testMissedPartHandler->addMissingParts(array_unique($headersReceived), $group['id']); } return; } // Normal path: process and insert. $failedInserts = $this->testHeaderStorage->store($parsedHeaders, $group, $enablePartRepair); if ($enablePartRepair && ! empty($failedInserts)) { $this->testMissedPartHandler->addMissingParts($failedInserts, $group['id']); } } }