mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-11-04 19:03:31 +01:00
An M3U can list tens of thousands of items, and the import started one background vod_import_item per item from the web request: that many processes and TMDb requests at once. The request now writes the items to a batch file (one JSON payload per line) and starts a single `vod_import_batch`, which feeds them through Multithread::pool(): at most thread_count imports at a time, commands read from the file only as slots free up, output discarded, polled every 100 ms. The payload no longer carries the whole genre map; the importer reads it from core. The batch writes a .wpid, so Kill Running stops it. thread_count (parallel imports) moves to Settings -> VOD Import, since core now uses it; VodItemImporter::importThreads() is the one reader for the import and the watch module's scans. saveGenreMap is simplified. Multithread::pool() is new beside the existing run(), which holds every command up front, spins without sleeping and keeps each finished process' pipes open; the watch cron moves to pool() too.
64 lines
1.9 KiB
PHP
64 lines
1.9 KiB
PHP
<?php
|
|
|
|
use XcVm\Core\Process\Multithread;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Multithread::pool() runs every command, never more than the pool size at
|
|
* once, and pulls commands from a generator only as slots free up. Each
|
|
* command logs its start and end; the log shows the overlap.
|
|
*/
|
|
final class MultithreadPoolTest extends TestCase {
|
|
|
|
private string $log;
|
|
|
|
protected function setUp(): void {
|
|
$this->log = tempnam(sys_get_temp_dir(), 'pool');
|
|
}
|
|
|
|
protected function tearDown(): void {
|
|
@unlink($this->log);
|
|
}
|
|
|
|
private function command(int $rID): string {
|
|
return 'echo s >> ' . escapeshellarg($this->log) . '; sleep 0.2; echo e' . $rID . ' >> ' . escapeshellarg($this->log);
|
|
}
|
|
|
|
/** Highest number of commands running at the same time, from the log. */
|
|
private function maxConcurrent(): int {
|
|
$rRunning = $rMax = 0;
|
|
foreach (file($this->log, FILE_IGNORE_NEW_LINES) as $rLine) {
|
|
$rRunning += ($rLine === 's') ? 1 : -1;
|
|
$rMax = max($rMax, $rRunning);
|
|
}
|
|
return $rMax;
|
|
}
|
|
|
|
public function testRunsEveryCommandWithinThePoolSize(): void {
|
|
$this->assertSame(6, Multithread::pool(array_map([$this, 'command'], range(1, 6)), 2, 10000));
|
|
|
|
$this->assertCount(12, file($this->log, FILE_IGNORE_NEW_LINES), 'every command started and finished');
|
|
$this->assertSame(2, $this->maxConcurrent());
|
|
}
|
|
|
|
public function testTakesCommandsFromAGeneratorOnlyAsSlotsFree(): void {
|
|
$rTaken = 0;
|
|
$rCommands = (function () use (&$rTaken) {
|
|
foreach (range(1, 3) as $rID) {
|
|
$rTaken++;
|
|
yield $this->command($rID);
|
|
}
|
|
})();
|
|
|
|
$this->assertSame(3, Multithread::pool($rCommands, 1, 10000));
|
|
$this->assertSame(3, $rTaken);
|
|
$this->assertSame(1, $this->maxConcurrent());
|
|
}
|
|
|
|
public function testANonPositiveSizeStillRunsOneAtATime(): void {
|
|
Multithread::pool([$this->command(1), $this->command(2)], 0, 10000);
|
|
|
|
$this->assertSame(1, $this->maxConcurrent());
|
|
}
|
|
}
|