Просмотр файла vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php

Размер файла: 5.22Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace Doctrine\Common\Cache;
  6.  
  7. use DateTime;
  8. use MongoDB\BSON\Binary;
  9. use MongoDB\BSON\UTCDateTime;
  10. use MongoDB\Collection;
  11. use MongoDB\Database;
  12. use MongoDB\Driver\Exception\Exception;
  13. use MongoDB\Model\BSONDocument;
  14.  
  15. use function serialize;
  16. use function time;
  17. use function unserialize;
  18.  
  19. /**
  20. * MongoDB cache provider for ext-mongodb
  21. *
  22. * @deprecated Deprecated without replacement in doctrine/cache 1.11. This class will be dropped in 2.0
  23. */
  24. class ExtMongoDBCache extends CacheProvider
  25. {
  26. /** @var Database */
  27. private $database;
  28.  
  29. /** @var Collection */
  30. private $collection;
  31.  
  32. /** @var bool */
  33. private $expirationIndexCreated = false;
  34.  
  35. /**
  36. * This provider will default to the write concern and read preference
  37. * options set on the Database instance (or inherited from MongoDB or
  38. * Client). Using an unacknowledged write concern (< 1) may make the return
  39. * values of delete() and save() unreliable. Reading from secondaries may
  40. * make contain() and fetch() unreliable.
  41. *
  42. * @see http://www.php.net/manual/en/mongo.readpreferences.php
  43. * @see http://www.php.net/manual/en/mongo.writeconcerns.php
  44. */
  45. public function __construct(Collection $collection)
  46. {
  47. // Ensure there is no typemap set - we want to use our own
  48. $this->collection = $collection->withOptions(['typeMap' => null]);
  49. $this->database = new Database($collection->getManager(), $collection->getDatabaseName());
  50. }
  51.  
  52. /**
  53. * {@inheritdoc}
  54. */
  55. protected function doFetch($id)
  56. {
  57. $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::DATA_FIELD, MongoDBCache::EXPIRATION_FIELD]);
  58.  
  59. if ($document === null) {
  60. return false;
  61. }
  62.  
  63. if ($this->isExpired($document)) {
  64. $this->createExpirationIndex();
  65. $this->doDelete($id);
  66.  
  67. return false;
  68. }
  69.  
  70. return unserialize($document[MongoDBCache::DATA_FIELD]->getData());
  71. }
  72.  
  73. /**
  74. * {@inheritdoc}
  75. */
  76. protected function doContains($id)
  77. {
  78. $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::EXPIRATION_FIELD]);
  79.  
  80. if ($document === null) {
  81. return false;
  82. }
  83.  
  84. if ($this->isExpired($document)) {
  85. $this->createExpirationIndex();
  86. $this->doDelete($id);
  87.  
  88. return false;
  89. }
  90.  
  91. return true;
  92. }
  93.  
  94. /**
  95. * {@inheritdoc}
  96. */
  97. protected function doSave($id, $data, $lifeTime = 0)
  98. {
  99. try {
  100. $this->collection->updateOne(
  101. ['_id' => $id],
  102. [
  103. '$set' => [
  104. MongoDBCache::EXPIRATION_FIELD => ($lifeTime > 0 ? new UTCDateTime((time() + $lifeTime) * 1000) : null),
  105. MongoDBCache::DATA_FIELD => new Binary(serialize($data), Binary::TYPE_GENERIC),
  106. ],
  107. ],
  108. ['upsert' => true]
  109. );
  110. } catch (Exception $e) {
  111. return false;
  112. }
  113.  
  114. return true;
  115. }
  116.  
  117. /**
  118. * {@inheritdoc}
  119. */
  120. protected function doDelete($id)
  121. {
  122. try {
  123. $this->collection->deleteOne(['_id' => $id]);
  124. } catch (Exception $e) {
  125. return false;
  126. }
  127.  
  128. return true;
  129. }
  130.  
  131. /**
  132. * {@inheritdoc}
  133. */
  134. protected function doFlush()
  135. {
  136. try {
  137. // Use remove() in lieu of drop() to maintain any collection indexes
  138. $this->collection->deleteMany([]);
  139. } catch (Exception $e) {
  140. return false;
  141. }
  142.  
  143. return true;
  144. }
  145.  
  146. /**
  147. * {@inheritdoc}
  148. */
  149. protected function doGetStats()
  150. {
  151. $uptime = null;
  152. $memoryUsage = null;
  153.  
  154. try {
  155. $serverStatus = $this->database->command([
  156. 'serverStatus' => 1,
  157. 'locks' => 0,
  158. 'metrics' => 0,
  159. 'recordStats' => 0,
  160. 'repl' => 0,
  161. ])->toArray()[0];
  162. $uptime = $serverStatus['uptime'] ?? null;
  163. } catch (Exception $e) {
  164. }
  165.  
  166. try {
  167. $collStats = $this->database->command(['collStats' => $this->collection->getCollectionName()])->toArray()[0];
  168. $memoryUsage = $collStats['size'] ?? null;
  169. } catch (Exception $e) {
  170. }
  171.  
  172. return [
  173. Cache::STATS_HITS => null,
  174. Cache::STATS_MISSES => null,
  175. Cache::STATS_UPTIME => $uptime,
  176. Cache::STATS_MEMORY_USAGE => $memoryUsage,
  177. Cache::STATS_MEMORY_AVAILABLE => null,
  178. ];
  179. }
  180.  
  181. /**
  182. * Check if the document is expired.
  183. */
  184. private function isExpired(BSONDocument $document): bool
  185. {
  186. return isset($document[MongoDBCache::EXPIRATION_FIELD]) &&
  187. $document[MongoDBCache::EXPIRATION_FIELD] instanceof UTCDateTime &&
  188. $document[MongoDBCache::EXPIRATION_FIELD]->toDateTime() < new DateTime();
  189. }
  190.  
  191. private function createExpirationIndex(): void
  192. {
  193. if ($this->expirationIndexCreated) {
  194. return;
  195. }
  196.  
  197. $this->collection->createIndex([MongoDBCache::EXPIRATION_FIELD => 1], ['background' => true, 'expireAfterSeconds' => 0]);
  198. }
  199. }