MonitorContext.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis;
  11. /**
  12. * Client-side abstraction of a Redis MONITOR context.
  13. *
  14. * @author Daniele Alessandri <suppakilla@gmail.com>
  15. */
  16. class MonitorContext implements \Iterator
  17. {
  18. private $client;
  19. private $isValid;
  20. private $position;
  21. /**
  22. * @param Client Client instance used by the context.
  23. */
  24. public function __construct(Client $client)
  25. {
  26. $this->checkCapabilities($client);
  27. $this->client = $client;
  28. $this->openContext();
  29. }
  30. /**
  31. * Automatically closes the context when PHP's garbage collector kicks in.
  32. */
  33. public function __destruct()
  34. {
  35. $this->closeContext();
  36. }
  37. /**
  38. * Checks if the passed client instance satisfies the required conditions
  39. * needed to initialize a monitor context.
  40. *
  41. * @param Client Client instance used by the context.
  42. */
  43. private function checkCapabilities(Client $client)
  44. {
  45. if (Helpers::isCluster($client->getConnection())) {
  46. throw new ClientException(
  47. 'Cannot initialize a monitor context over a cluster of connections'
  48. );
  49. }
  50. if ($client->getProfile()->supportsCommand('monitor') === false) {
  51. throw new ClientException(
  52. 'The current profile does not support the MONITOR command'
  53. );
  54. }
  55. }
  56. /**
  57. * Initializes the context and sends the MONITOR command to the server.
  58. *
  59. * @param Client Client instance used by the context.
  60. */
  61. protected function openContext()
  62. {
  63. $this->isValid = true;
  64. $monitor = $this->client->createCommand('monitor');
  65. $this->client->executeCommand($monitor);
  66. }
  67. /**
  68. * Closes the context. Internally this is done by disconnecting from server
  69. * since there is no way to terminate the stream initialized by MONITOR.
  70. */
  71. public function closeContext()
  72. {
  73. $this->client->disconnect();
  74. $this->isValid = false;
  75. }
  76. /**
  77. * {@inheritdoc}
  78. */
  79. public function rewind()
  80. {
  81. // NOOP
  82. }
  83. /**
  84. * Returns the last message payload retrieved from the server.
  85. *
  86. * @return Object
  87. */
  88. public function current()
  89. {
  90. return $this->getValue();
  91. }
  92. /**
  93. * {@inheritdoc}
  94. */
  95. public function key()
  96. {
  97. return $this->position;
  98. }
  99. /**
  100. * {@inheritdoc}
  101. */
  102. public function next()
  103. {
  104. $this->position++;
  105. }
  106. /**
  107. * Checks if the the context is still in a valid state to continue.
  108. *
  109. * @return Boolean
  110. */
  111. public function valid()
  112. {
  113. return $this->isValid;
  114. }
  115. /**
  116. * Waits for a new message from the server generated by MONITOR and
  117. * returns it when available.
  118. *
  119. * @return Object
  120. */
  121. private function getValue()
  122. {
  123. $database = 0;
  124. $event = $this->client->getConnection()->read();
  125. $callback = function($matches) use (&$database) {
  126. if (isset($matches[1])) {
  127. $database = (int) $matches[1];
  128. }
  129. return ' ';
  130. };
  131. $event = preg_replace_callback('/ \(db (\d+)\) /', $callback, $event, 1);
  132. @list($timestamp, $command, $arguments) = split(' ', $event, 3);
  133. return (object) array(
  134. 'timestamp' => (float) $timestamp,
  135. 'database' => $database,
  136. 'command' => substr($command, 1, -1),
  137. 'arguments' => $arguments,
  138. );
  139. }
  140. }