Files
AndyTranscribe/app/Services/DiskSpaceService.php
T
ben 771ee8db5a Add Docker stack, Reverb live progress, and duplicate upload detection.
Ship FrankenPHP Compose services with Reverb WebSockets for real-time transcription status, skip re-uploading identical audio via content hash, and format disk usage without requiring intl.
2026-08-12 17:35:48 +02:00

98 lines
2.7 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
class DiskSpaceService
{
/**
* Snapshot of free/used space for the recordings storage volume.
*
* @return array{
* total_bytes: int,
* free_bytes: int,
* used_bytes: int,
* used_percent: float,
* free_percent: float,
* total_human: string,
* free_human: string,
* used_human: string
* }|null
*/
public function snapshot(?string $path = null): ?array
{
$path ??= Storage::disk('local')->path('');
if (! is_dir($path)) {
@mkdir($path, 0755, true);
}
/** @var array{total_bytes: int, free_bytes: int, used_bytes: int, used_percent: float, free_percent: float, total_human: string, free_human: string, used_human: string}|null */
return Cache::remember(
'disk-space:'.md5($path),
now()->addSeconds(30),
fn () => $this->measure($path),
);
}
/**
* @return array{
* total_bytes: int,
* free_bytes: int,
* used_bytes: int,
* used_percent: float,
* free_percent: float,
* total_human: string,
* free_human: string,
* used_human: string
* }|null
*/
private function measure(string $path): ?array
{
$total = @disk_total_space($path);
$free = @disk_free_space($path);
if ($total === false || $free === false || $total <= 0) {
return null;
}
$totalBytes = (int) $total;
$freeBytes = (int) max(0, $free);
$usedBytes = (int) max(0, $totalBytes - $freeBytes);
$usedPercent = round(($usedBytes / $totalBytes) * 100, 1);
$freePercent = round(($freeBytes / $totalBytes) * 100, 1);
return [
'total_bytes' => $totalBytes,
'free_bytes' => $freeBytes,
'used_bytes' => $usedBytes,
'used_percent' => $usedPercent,
'free_percent' => $freePercent,
'total_human' => $this->formatBytes($totalBytes),
'free_human' => $this->formatBytes($freeBytes),
'used_human' => $this->formatBytes($usedBytes),
];
}
/**
* Human-readable byte size without requiring the intl extension.
*/
private function formatBytes(int $bytes): string
{
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
$value = (float) max(0, $bytes);
$unit = 0;
while ($value >= 1024 && $unit < count($units) - 1) {
$value /= 1024;
$unit++;
}
$precision = $unit === 0 ? 0 : 1;
return number_format($value, $precision).' '.$units[$unit];
}
}