c86f790ad4690abba7f467de7c754eefdfba3f35
[civicrm-core.git] / CRM / Queue / Service.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * The queue service provides an interface for creating or locating
14 * queues. Note that this approach hides the details of data-storage:
15 * different queue-providers may store the queue content in different
16 * ways (in memory, in SQL, or in an external service).
17 *
18 * @code
19 * $queue = CRM_Queue_Service::singleton()->create(array(
20 * 'type' => 'interactive',
21 * 'name' => 'upgrade-tasks',
22 * ));
23 * $queue->createItem($myData);
24 *
25 * // Some time later...
26 * $item = $queue->claimItem();
27 * if ($item) {
28 * if (my_process($item->data)) {
29 * $queue->deleteItem($item);
30 * } else {
31 * $queue->releaseItem($item);
32 * }
33 * }
34 * @endcode
35 */
36 class CRM_Queue_Service {
37
38 protected static $_singleton;
39
40 /**
41 * FIXME: Singleton pattern should be removed when dependency-injection
42 * becomes available.
43 *
44 * @param bool $forceNew
45 * TRUE if a new instance must be created.
46 *
47 * @return \CRM_Queue_Service
48 */
49 public static function &singleton($forceNew = FALSE) {
50 if ($forceNew || !self::$_singleton) {
51 self::$_singleton = new CRM_Queue_Service();
52 }
53 return self::$_singleton;
54 }
55
56 /**
57 * Queues.
58 *
59 * Format is (string $queueName => CRM_Queue_Queue).
60 *
61 * @var array
62 */
63 public $queues;
64
65 /**
66 * Class constructor.
67 */
68 public function __construct() {
69 $this->queues = [];
70 }
71
72 /**
73 * Create a queue. If one already exists, then it will be reused.
74 *
75 * @param array $queueSpec
76 * Array with keys:
77 * - type: string, required, e.g. "interactive", "immediate", "stomp",
78 * "beanstalk"
79 * - name: string, required, e.g. "upgrade-tasks"
80 * - reset: bool, optional; if a queue is found, then it should be
81 * flushed; default to TRUE
82 * - (additional keys depending on the queue provider).
83 *
84 * @return CRM_Queue_Queue
85 */
86 public function create($queueSpec) {
87 if (@is_object($this->queues[$queueSpec['name']]) && empty($queueSpec['reset'])) {
88 return $this->queues[$queueSpec['name']];
89 }
90
91 $queue = $this->instantiateQueueObject($queueSpec);
92 $exists = $queue->existsQueue();
93 if (!$exists) {
94 $queue->createQueue();
95 }
96 elseif (@$queueSpec['reset']) {
97 $queue->deleteQueue();
98 $queue->createQueue();
99 }
100 else {
101 $queue->loadQueue();
102 }
103 $this->queues[$queueSpec['name']] = $queue;
104 return $queue;
105 }
106
107 /**
108 * Look up an existing queue.
109 *
110 * @param array $queueSpec
111 * Array with keys:
112 * - type: string, required, e.g. "interactive", "immediate", "stomp",
113 * "beanstalk"
114 * - name: string, required, e.g. "upgrade-tasks"
115 * - (additional keys depending on the queue provider).
116 *
117 * @return CRM_Queue_Queue
118 */
119 public function load($queueSpec) {
120 if (is_object($this->queues[$queueSpec['name']])) {
121 return $this->queues[$queueSpec['name']];
122 }
123 $queue = $this->instantiateQueueObject($queueSpec);
124 $queue->loadQueue();
125 $this->queues[$queueSpec['name']] = $queue;
126 return $queue;
127 }
128
129 /**
130 * Convert a queue "type" name to a class name.
131 *
132 * @param string $type
133 * E.g. "interactive", "immediate", "stomp", "beanstalk".
134 *
135 * @return string
136 * Class-name
137 */
138 protected function getQueueClass($type) {
139 $type = preg_replace('/[^a-zA-Z0-9]/', '', $type);
140 $className = 'CRM_Queue_Queue_' . $type;
141 // FIXME: when used with class-autoloader, this may be unnecessary
142 if (!class_exists($className)) {
143 $classFile = 'CRM/Queue/Queue/' . $type . '.php';
144 require_once $classFile;
145 }
146 return $className;
147 }
148
149 /**
150 * @param array $queueSpec
151 * See create().
152 *
153 * @return CRM_Queue_Queue
154 */
155 protected function instantiateQueueObject($queueSpec) {
156 // note: you should probably never do anything else here
157 $class = new ReflectionClass($this->getQueueClass($queueSpec['type']));
158 return $class->newInstance($queueSpec);
159 }
160
161 }