PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Doctrine/MongoDB/CommandCursor.php

http://github.com/doctrine/mongodb
PHP | 260 lines | 111 code | 31 blank | 118 comment | 5 complexity | b2245ee6f7afa4d1d3a93aa6c85708fe MD5 | raw file
  1. <?php
  2. namespace Doctrine\MongoDB;
  3. use BadMethodCallException;
  4. use MongoCommandCursor;
  5. /**
  6. * Wrapper for the PHP MongoCommandCursor class.
  7. *
  8. * @since 1.2
  9. * @author Jeremy Mikola <jmikola@gmail.com>
  10. */
  11. class CommandCursor implements Iterator
  12. {
  13. /**
  14. * The MongoCommandCursor instance being wrapped.
  15. *
  16. * @var MongoCommandCursor
  17. */
  18. private $mongoCommandCursor;
  19. /**
  20. * Number of times to retry queries.
  21. *
  22. * @var integer
  23. */
  24. private $numRetries;
  25. private $batchSize;
  26. private $timeout;
  27. /**
  28. * Constructor.
  29. *
  30. * @param MongoCommandCursor $mongoCommandCursor MongoCommandCursor instance being wrapped
  31. * @param integer $numRetries Number of times to retry queries
  32. */
  33. public function __construct(MongoCommandCursor $mongoCommandCursor, $numRetries = 0)
  34. {
  35. $this->mongoCommandCursor = $mongoCommandCursor;
  36. $this->numRetries = (integer) $numRetries;
  37. }
  38. /**
  39. * Wrapper method for MongoCommandCursor::batchSize().
  40. *
  41. * @see http://php.net/manual/en/mongocommandcursor.batchsize.php
  42. * @param integer $num
  43. * @return $this
  44. */
  45. public function batchSize($num)
  46. {
  47. $this->batchSize = (integer) $num;
  48. $this->mongoCommandCursor->batchSize($num);
  49. return $this;
  50. }
  51. /**
  52. * Recreates the command cursor and counts its results.
  53. *
  54. * @see http://php.net/manual/en/countable.count.php
  55. * @return integer
  56. */
  57. public function count()
  58. {
  59. $cursor = $this;
  60. return $this->retry(function() use ($cursor) {
  61. return iterator_count($cursor);
  62. });
  63. }
  64. /**
  65. * Wrapper method for MongoCommandCursor::current().
  66. *
  67. * @see http://php.net/manual/en/iterator.current.php
  68. * @see http://php.net/manual/en/mongocommandcursor.current.php
  69. * @return array|null
  70. */
  71. public function current()
  72. {
  73. return $this->mongoCommandCursor->current();
  74. }
  75. /**
  76. * Wrapper method for MongoCommandCursor::dead().
  77. *
  78. * @see http://php.net/manual/en/mongocommandcursor.dead.php
  79. * @return boolean
  80. */
  81. public function dead()
  82. {
  83. return $this->mongoCommandCursor->dead();
  84. }
  85. /**
  86. * Returns the MongoCommandCursor instance being wrapped.
  87. *
  88. * @return \MongoCommandCursor
  89. */
  90. public function getMongoCommandCursor()
  91. {
  92. return $this->mongoCommandCursor;
  93. }
  94. /**
  95. * Rewind the cursor and return its first result.
  96. *
  97. * @see Iterator::getSingleResult()
  98. * @return array|null
  99. */
  100. public function getSingleResult()
  101. {
  102. $result = null;
  103. foreach ($this as $result) {
  104. break;
  105. }
  106. /* Avoid rewinding the cursor here, as that would re-execute the
  107. * command prematurely and later iteration will rewind on its own.
  108. */
  109. return $result;
  110. }
  111. /**
  112. * Wrapper method for MongoCommandCursor::info().
  113. *
  114. * @see http://php.net/manual/en/mongocommandcursor.info.php
  115. * @return array
  116. */
  117. public function info()
  118. {
  119. return $this->mongoCommandCursor->info();
  120. }
  121. /**
  122. * Wrapper method for MongoCommandCursor::key().
  123. *
  124. * @see http://php.net/manual/en/iterator.key.php
  125. * @see http://php.net/manual/en/mongocommandcursor.key.php
  126. * @return integer
  127. */
  128. public function key()
  129. {
  130. return $this->mongoCommandCursor->key();
  131. }
  132. /**
  133. * Wrapper method for MongoCommandCursor::next().
  134. *
  135. * @see http://php.net/manual/en/iterator.next.php
  136. * @see http://php.net/manual/en/mongocommandcursor.next.php
  137. */
  138. public function next()
  139. {
  140. $cursor = $this;
  141. $this->retry(function() use ($cursor) {
  142. $cursor->getMongoCommandCursor()->next();
  143. });
  144. }
  145. /**
  146. * Wrapper method for MongoCommandCursor::rewind().
  147. *
  148. * @see http://php.net/manual/en/iterator.rewind.php
  149. * @see http://php.net/manual/en/mongocommandcursor.rewind.php
  150. * @return array
  151. */
  152. public function rewind()
  153. {
  154. $cursor = $this;
  155. return $this->retry(function() use ($cursor) {
  156. return $cursor->getMongoCommandCursor()->rewind();
  157. });
  158. }
  159. /**
  160. * Wrapper method for MongoCommandCursor::timeout().
  161. *
  162. * @see http://php.net/manual/en/mongocommandcursor.timeout.php
  163. * @param integer $ms
  164. * @return $this
  165. * @throws BadMethodCallException if MongoCommandCursor::timeout() is not available
  166. */
  167. public function timeout($ms)
  168. {
  169. if ( ! method_exists('MongoCommandCursor', 'timeout')) {
  170. throw new BadMethodCallException('MongoCommandCursor::timeout() is not available');
  171. }
  172. $this->timeout = (integer) $ms;
  173. $this->mongoCommandCursor->timeout($ms);
  174. return $this;
  175. }
  176. /**
  177. * Return the cursor's results as an array.
  178. *
  179. * @see Iterator::toArray()
  180. * @return array
  181. */
  182. public function toArray()
  183. {
  184. $cursor = $this;
  185. return $this->retry(function() use ($cursor) {
  186. return iterator_to_array($cursor);
  187. });
  188. }
  189. /**
  190. * Wrapper method for MongoCommandCursor::valid().
  191. *
  192. * @see http://php.net/manual/en/iterator.valid.php
  193. * @see http://php.net/manual/en/mongocommandcursor.valid.php
  194. * @return boolean
  195. */
  196. public function valid()
  197. {
  198. return $this->mongoCommandCursor->valid();
  199. }
  200. /**
  201. * Conditionally retry a closure if it yields an exception.
  202. *
  203. * If the closure does not return successfully within the configured number
  204. * of retries, its first exception will be thrown.
  205. *
  206. * @param \Closure $retry
  207. * @return mixed
  208. */
  209. protected function retry(\Closure $retry)
  210. {
  211. if ($this->numRetries < 1) {
  212. return $retry();
  213. }
  214. $firstException = null;
  215. for ($i = 0; $i <= $this->numRetries; $i++) {
  216. try {
  217. return $retry();
  218. } catch (\MongoCursorException $e) {
  219. } catch (\MongoConnectionException $e) {
  220. }
  221. if ($firstException === null) {
  222. $firstException = $e;
  223. }
  224. if ($i === $this->numRetries) {
  225. throw $firstException;
  226. }
  227. }
  228. }
  229. }