Memory.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Cache\Collector;
  12. use Carbon\Carbon;
  13. use Hyperf\Coordinator\Constants;
  14. use Hyperf\Coordinator\CoordinatorManager;
  15. use Hyperf\Coroutine\Coroutine;
  16. use Hyperf\Stringable\Str;
  17. final class Memory
  18. {
  19. /**
  20. * @var array<string, null|Carbon>
  21. */
  22. private array $keys = [];
  23. /**
  24. * @var array<string, mixed>
  25. */
  26. private array $values = [];
  27. private ?int $loopCid = null;
  28. private ?int $waitCloseCid = null;
  29. private bool $stopped = false;
  30. public static function instance(): static
  31. {
  32. static $instance;
  33. return $instance ??= new self();
  34. }
  35. public function size(): int
  36. {
  37. return count($this->keys);
  38. }
  39. public function has(string $key): bool
  40. {
  41. return isset($this->keys[$key]);
  42. }
  43. public function get(string $key, mixed $default = null): mixed
  44. {
  45. return $this->values[$key] ?? $default;
  46. }
  47. public function set(string $key, mixed $value, ?Carbon $ttl = null): bool
  48. {
  49. $this->loop();
  50. $this->keys[$key] = $ttl;
  51. $this->values[$key] = $value;
  52. return true;
  53. }
  54. public function delete(string $key): bool
  55. {
  56. unset($this->keys[$key], $this->values[$key]);
  57. return true;
  58. }
  59. public function clear(): bool
  60. {
  61. $this->keys = [];
  62. $this->values = [];
  63. return true;
  64. }
  65. public function clearPrefix(string $prefix): bool
  66. {
  67. foreach ($this->keys as $key => $ttl) {
  68. if (Str::startsWith($key, $prefix)) {
  69. $this->delete($key);
  70. }
  71. }
  72. return true;
  73. }
  74. private function loop(): void
  75. {
  76. $this->loopCid ??= Coroutine::create(function () {
  77. while (true) {
  78. foreach ($this->keys as $key => $ttl) {
  79. if ($ttl instanceof Carbon && Carbon::now()->gt($ttl)) {
  80. $this->delete($key);
  81. }
  82. }
  83. sleep(1);
  84. if ($this->stopped || $this->size() === 0) {
  85. break;
  86. }
  87. }
  88. $this->loopCid = null;
  89. $this->stopped = false;
  90. });
  91. $this->waitCloseCid ??= Coroutine::create(function () {
  92. CoordinatorManager::until(Constants::WORKER_EXIT)->yield();
  93. $this->stopped = true;
  94. $this->clear();
  95. $this->waitCloseCid = null;
  96. });
  97. }
  98. }