DiskSpaceMonitor.php 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Services;
  4. use Illuminate\Support\Facades\Cache;
  5. use Throwable;
  6. class DiskSpaceMonitor
  7. {
  8. private const CACHE_KEY = 'disk_space_monitor.status';
  9. /**
  10. * @return array{warning: bool, free_bytes: int|null, threshold_bytes: int, path: string, checked_at: string|null}
  11. */
  12. public function status(): array
  13. {
  14. try {
  15. return Cache::remember(
  16. self::CACHE_KEY,
  17. now()->addSeconds($this->cacheSeconds()),
  18. fn (): array => $this->freshStatus()
  19. );
  20. } catch (Throwable) {
  21. return $this->freshStatus();
  22. }
  23. }
  24. public function formatBytes(?int $bytes): string
  25. {
  26. if ($bytes === null) {
  27. return 'неизвестно';
  28. }
  29. $units = ['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'];
  30. $value = (float) $bytes;
  31. $unitIndex = 0;
  32. while ($value >= 1024 && $unitIndex < count($units) - 1) {
  33. $value /= 1024;
  34. $unitIndex++;
  35. }
  36. return sprintf('%s %s', round($value, $unitIndex === 0 ? 0 : 2), $units[$unitIndex]);
  37. }
  38. /**
  39. * @return array{warning: bool, free_bytes: int|null, threshold_bytes: int, path: string, checked_at: string|null}
  40. */
  41. private function freshStatus(): array
  42. {
  43. $path = $this->path();
  44. $thresholdBytes = $this->thresholdBytes();
  45. $freeBytes = @disk_free_space($path);
  46. $freeBytes = $freeBytes === false ? null : (int) $freeBytes;
  47. return [
  48. 'warning' => $freeBytes !== null && $freeBytes < $thresholdBytes,
  49. 'free_bytes' => $freeBytes,
  50. 'threshold_bytes' => $thresholdBytes,
  51. 'path' => $path,
  52. 'checked_at' => now()->toDateTimeString(),
  53. ];
  54. }
  55. private function path(): string
  56. {
  57. return (string) config('app.disk_space_warning.path', storage_path());
  58. }
  59. private function thresholdBytes(): int
  60. {
  61. return max(0, (int) config('app.disk_space_warning.threshold_bytes', 1024 * 1024 * 1024));
  62. }
  63. private function cacheSeconds(): int
  64. {
  65. return max(1, (int) config('app.disk_space_warning.cache_seconds', 300));
  66. }
  67. }