GearmanCacheWrapper.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. namespace Mmoreram\GearmanBundle\Service;
  3. use Symfony\Component\Config\FileLocator;
  4. use Doctrine\Common\Annotations\AnnotationReader;
  5. use Doctrine\Common\Annotations\AnnotationRegistry;
  6. use Symfony\Component\HttpKernel\Kernel;
  7. use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
  8. use Doctrine\Common\Cache\Cache;
  9. use Mmoreram\GearmanBundle\Module\WorkerCollection;
  10. use Mmoreram\GearmanBundle\Module\WorkerDirectoryLoader;
  11. use Mmoreram\GearmanBundle\Module\WorkerClass as Worker;
  12. use Mmoreram\GearmanBundle\Driver\Gearman\Work;
  13. use ReflectionClass;
  14. /**
  15. * Gearman cache loader class
  16. *
  17. * @author Marc Morera <yuhu@mmoreram.com>
  18. */
  19. class GearmanCacheWrapper
  20. {
  21. /**
  22. * Bundles loaded by kernel
  23. *
  24. * @var Array
  25. */
  26. private $kernelBundles;
  27. /**
  28. * Bundles available to perform search
  29. *
  30. * @var Array
  31. */
  32. private $bundles;
  33. /**
  34. * @var Array
  35. *
  36. * bundles to parse on
  37. */
  38. private $bundlesAccepted = array();
  39. /**
  40. * @var Array
  41. *
  42. * accepted namespaces
  43. */
  44. private $namespacesAccepted = array();
  45. /**
  46. * @var Array
  47. *
  48. * Ignored namespaces
  49. */
  50. private $namespacesIgnored = array();
  51. /**
  52. * @var GearmanCache
  53. *
  54. * Gearman Cache
  55. */
  56. private $cache;
  57. /**
  58. * @var string
  59. *
  60. * Gearman cache id
  61. */
  62. private $cacheId;
  63. /**
  64. * @var array
  65. *
  66. * WorkerCollection with all workers and jobs available
  67. */
  68. private $workerCollection;
  69. /**
  70. * @var array
  71. *
  72. * Collection of servers to connect
  73. */
  74. private $servers;
  75. /**
  76. * @var array
  77. *
  78. * Default settings defined by user in config.yml
  79. */
  80. private $defaultSettings;
  81. /**
  82. * Return workerCollection
  83. *
  84. * @return array all available workers
  85. */
  86. public function getWorkers()
  87. {
  88. return $this->workerCollection;
  89. }
  90. /**
  91. * Construct method
  92. *
  93. * @param array $bundles Bundles
  94. */
  95. public function __construct(Kernel $kernel, Cache $cache, $cacheId, array $bundles, array $servers, array $defaultSettings)
  96. {
  97. $this->kernelBundles = $kernel->getBundles();
  98. $this->bundles = $bundles;
  99. $this->cache = $cache;
  100. $this->cacheId = $cacheId;
  101. $this->servers = $servers;
  102. $this->defaultSettings = $defaultSettings;
  103. }
  104. /**
  105. * loads Gearman cache, only if is not loaded yet
  106. *
  107. * @return GearmanCacheLoader self Object
  108. */
  109. public function load()
  110. {
  111. if ($this->cache->contains($this->cacheId)) {
  112. $this->workerCollection = $this->cache->get($this->cacheId);
  113. } else {
  114. $this->workerCollection = $this->parseNamespaceMap()->toArray();
  115. $this->cache->save($this->cacheId, $this->workerCollection);
  116. }
  117. return $this;
  118. }
  119. /**
  120. * flush all cache
  121. *
  122. * @return GearmanCacheLoader self Object
  123. */
  124. public function flush()
  125. {
  126. $this->cache->delete($this->cacheId);
  127. return $this;
  128. }
  129. /**
  130. * Return Gearman bundle settings, previously loaded by method load()
  131. * If settings are not loaded, a SettingsNotLoadedException Exception is thrown
  132. *
  133. * @return array Bundles that gearman will be able to search annotations
  134. */
  135. public function loadNamespaceMap()
  136. {
  137. foreach ($this->bundles as $bundleSettings) {
  138. $bundleNamespace = $bundleSettings['namespace'];
  139. if ($bundleSettings['active']) {
  140. $this->bundlesAccepted[] = $bundleNamespace;
  141. if (!empty($bundleSettings['include'])) {
  142. foreach ($bundleSettings['include'] as $include) {
  143. $this->namespacesAccepted[] = $bundleNamespace . '\\' . $include;
  144. }
  145. } else {
  146. /**
  147. * If no include is set, include all namespace
  148. */
  149. $this->namespacesAccepted[] = $bundleNamespace;
  150. }
  151. foreach ($bundleSettings['ignore'] as $ignore) {
  152. $this->namespacesIgnored[] = $bundleNamespace . '\\' . $ignore;
  153. }
  154. }
  155. }
  156. }
  157. /**
  158. * Perform a parsing inside all namespace map
  159. *
  160. * @return WorkerCollection collection of all info
  161. */
  162. private function parseNamespaceMap()
  163. {
  164. AnnotationRegistry::registerFile(__DIR__ . "/../Driver/Gearman/Work.php");
  165. AnnotationRegistry::registerFile(__DIR__ . "/../Driver/Gearman/Job.php");
  166. /**
  167. * Depending on Symfony2 version
  168. */
  169. if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
  170. $reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader();
  171. $reader->addNamespace('Mmoreram\GearmanBundle\Driver');
  172. } else {
  173. $reader = new AnnotationReader();
  174. $reader->setDefaultAnnotationNamespace('Mmoreram\GearmanBundle\Driver\\');
  175. }
  176. $workerCollection = new WorkerCollection;
  177. foreach ($this->kernelBundles as $kernelBundle) {
  178. if (!in_array($kernelBundle->getNamespace(), $this->bundlesAccepted)) {
  179. continue;
  180. }
  181. $filesLoader = new WorkerDirectoryLoader(new FileLocator('.'));
  182. $files = $filesLoader->load($kernelBundle->getPath());
  183. foreach ($files as $file) {
  184. foreach ($this->namespacesIgnored as $namespaceIgnored) {
  185. if ($this->isSubNamespace($namespaceIgnored, $file['class'])) {
  186. continue 2;
  187. }
  188. }
  189. foreach ($this->namespacesAccepted as $namespaceAccepted) {
  190. if ($this->isSubNamespace($namespaceAccepted, $file['class'])) {
  191. /**
  192. * File is accepted to be parsed
  193. */
  194. $reflClass = new ReflectionClass($file['class']);
  195. $classAnnotations = $reader->getClassAnnotations($reflClass);
  196. foreach ($classAnnotations as $annot) {
  197. if ($annot instanceof Work) {
  198. $worker = new Worker($annot, $reflClass, $reader, $this->servers, $this->defaultSettings);
  199. $workerCollection->add($worker);
  200. }
  201. }
  202. continue 2;
  203. }
  204. }
  205. }
  206. }
  207. return $workerCollection;
  208. }
  209. /**
  210. * Checks if namespace is subnamespace of another
  211. *
  212. * @param string $namespace Parent namespace
  213. * @param string $subNamespace Namespace to check
  214. *
  215. * @return boolean
  216. */
  217. private function isSubNamespace($namespace, $subNamespace)
  218. {
  219. return ( strpos($subNamespace, $namespace) === 0 );
  220. }
  221. }