mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-25 19:03:14 +01:00
Review fixes for the php_pids change.
- cron:users judged a remote PHP-served connection by date_start, but a
reused connection (VOD range/seek, TS or timeshift reconnect) gets a new
worker pid and keeps its original date_start. A pid assigned after the
node's last heartbeat was then looked up in a list that could not hold
it, and the live viewer was killed. The pid write also stamps
hls_last_read (MAIN's clock), so the later of the two now dates the pid.
The check moves into isRemoteWorkerRunning().
- phpFpmWorkerPIDs() returns null when no FPM master is visible, so an
idle ondemand pool ("[]") now reaps dead workers' rows while an unknown
list still keeps them. A server missing from either map no longer hits
count(null).
- getAllSimple/getStreamingSimple/getProxySimple and the admin API
get_server leave out php_pids; getById keeps the full row for REPLACE.
- Tests pin the watchdog and reaper wiring, exercise sort(), and reset
the ServerRepository db seam; array_unique() is dropped (unreachable).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQHeypQpfAXTdCysmi7b6a
84 lines
3.4 KiB
PHP
84 lines
3.4 KiB
PHP
<?php
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use XcVm\Core\Process\ProcessManager;
|
|
|
|
/**
|
|
* ProcessManager::phpFpmWorkerPIDs — the pid list the watchdog publishes as
|
|
* servers.php_pids. A connection row's pid is the PHP-FPM worker serving it
|
|
* (getmypid() in live/vod/timeshift), so the list must hold the workers of
|
|
* the xc_vm pool. It used to hold the FPM master pids from the pool pid files,
|
|
* which never match a worker: in Redis mode MAIN's cron:users then closed
|
|
* every PHP-served LB viewer about a minute after it connected. An idle pool
|
|
* (pm = ondemand) has no workers, so [] means "none running" only while an FPM
|
|
* master is visible; with none, the list is unknown (null).
|
|
*
|
|
* Driven against a fixture /proc tree. Its pids are above the kernel's
|
|
* PID_MAX_LIMIT (4194304), so none can be this process's own pid, which
|
|
* findProcessPIDs() skips.
|
|
*/
|
|
final class PhpFpmWorkerPidsTest extends TestCase {
|
|
|
|
private string $rRoot;
|
|
|
|
protected function setUp(): void {
|
|
$this->rRoot = sys_get_temp_dir() . '/xcvm_proc_' . uniqid('', true);
|
|
mkdir($this->rRoot, 0755, true);
|
|
}
|
|
|
|
protected function tearDown(): void {
|
|
foreach (glob($this->rRoot . '/*/cmdline') ?: [] as $rFile) {
|
|
unlink($rFile);
|
|
rmdir(dirname($rFile));
|
|
}
|
|
@rmdir($this->rRoot);
|
|
}
|
|
|
|
private function process(int $rPID, string $rCmdline): void {
|
|
mkdir($this->rRoot . '/' . $rPID);
|
|
file_put_contents($this->rRoot . '/' . $rPID . '/cmdline', $rCmdline);
|
|
}
|
|
|
|
public function testListsTheXcVmPoolWorkersOnly(): void {
|
|
$this->process(4300001, "php-fpm: master process (/home/xc_vm/bin/php/etc/1.conf)\0");
|
|
// FPM overwrites the worker's argv with its title and pads the rest with NULs.
|
|
$this->process(4300002, 'php-fpm: pool xc_vm' . str_repeat("\0", 40));
|
|
$this->process(4300003, 'php-fpm: pool xc_vm');
|
|
$this->process(4300004, "/home/xc_vm/bin/php/bin/php\0console.php\0watchdog\0");
|
|
$this->process(4300005, 'php-fpm: pool www');
|
|
// Globbed before 4300002 ("43000010" < "4300002"); listed last (numeric order).
|
|
$this->process(43000010, 'php-fpm: pool xc_vm');
|
|
|
|
$this->assertSame([4300002, 4300003, 43000010], ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
}
|
|
|
|
public function testAnIdlePoolYieldsAnEmptyList(): void {
|
|
$this->process(4300001, "php-fpm: master process (/home/xc_vm/bin/php/etc/1.conf)\0");
|
|
|
|
$this->assertSame([], ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
}
|
|
|
|
public function testNoVisibleFpmMasterMeansUnknown(): void {
|
|
$this->assertNull(ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
|
|
$this->process(4300004, "/home/xc_vm/bin/php/bin/php\0console.php\0watchdog\0");
|
|
$this->assertNull(ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
}
|
|
|
|
public function testFindProcessPIDsReadsTheGivenProcRoot(): void {
|
|
$this->assertSame([], ProcessManager::findProcessPIDs(['x'], 0, $this->rRoot));
|
|
|
|
$this->process(4300007, "ffmpeg\0-i\0x\0");
|
|
$this->assertSame([4300007], ProcessManager::findProcessPIDs(['ffmpeg'], 0, $this->rRoot));
|
|
}
|
|
|
|
public function testWatchdogPublishesTheWorkerList(): void {
|
|
$rPath = MAIN_HOME . 'Cli/Commands/WatchdogCommand.php';
|
|
$this->assertFileExists($rPath);
|
|
$rSource = (string) file_get_contents($rPath);
|
|
|
|
$this->assertSame(1, substr_count($rSource, 'ProcessManager::phpFpmWorkerPIDs()'), 'the watchdog must publish the FPM worker pids as php_pids');
|
|
$this->assertStringNotContainsString('bin/php/sockets/*.pid', $rSource, 'the pool pid files hold only the FPM masters');
|
|
}
|
|
}
|