Merge pull request #14416 from JMAConsulting/core-785-1
[civicrm-core.git] / CRM / Queue / Service.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 * The queue service provides an interface for creating or locating
30 * queues. Note that this approach hides the details of data-storage:
31 * different queue-providers may store the queue content in different
32 * ways (in memory, in SQL, or in an external service).
33 *
34 * @code
35 * $queue = CRM_Queue_Service::singleton()->create(array(
36 * 'type' => 'interactive',
37 * 'name' => 'upgrade-tasks',
38 * ));
39 * $queue->createItem($myData);
40 *
41 * // Some time later...
42 * $item = $queue->claimItem();
5e74f823
TO
43 * if ($item) {
44 * if (my_process($item->data)) {
16e38e82 45 * $queue->deleteItem($item);
5e74f823 46 * } else {
16e38e82 47 * $queue->releaseItem($item);
5e74f823 48 * }
6a488035
TO
49 * }
50 * @endcode
51 */
52class CRM_Queue_Service {
53
4523a2f5 54 protected static $_singleton;
6a488035
TO
55
56 /**
57 * FIXME: Singleton pattern should be removed when dependency-injection
58 * becomes available.
59 *
4523a2f5
TO
60 * @param bool $forceNew
61 * TRUE if a new instance must be created.
77b97be7
EM
62 *
63 * @return \CRM_Queue_Service
6a488035 64 */
4523a2f5 65 public static function &singleton($forceNew = FALSE) {
6a488035
TO
66 if ($forceNew || !self::$_singleton) {
67 self::$_singleton = new CRM_Queue_Service();
68 }
69 return self::$_singleton;
70 }
71
72 /**
041ecc95 73 * Queues.
74 *
75 * Format is (string $queueName => CRM_Queue_Queue).
76 *
77 * @var array
6a488035 78 */
4523a2f5 79 public $queues;
e0ef6999
EM
80
81 /**
041ecc95 82 * Class constructor.
e0ef6999 83 */
4523a2f5 84 public function __construct() {
be2fb01f 85 $this->queues = [];
6a488035
TO
86 }
87
88 /**
4523a2f5
TO
89 * Create a queue. If one already exists, then it will be reused.
90 *
91 * @param array $queueSpec
92 * Array with keys:
93 * - type: string, required, e.g. "interactive", "immediate", "stomp",
94 * "beanstalk"
6a488035 95 * - name: string, required, e.g. "upgrade-tasks"
4523a2f5
TO
96 * - reset: bool, optional; if a queue is found, then it should be
97 * flushed; default to TRUE
98 * - (additional keys depending on the queue provider).
6a488035
TO
99 *
100 * @return CRM_Queue_Queue
101 */
4523a2f5 102 public function create($queueSpec) {
6a488035
TO
103 if (@is_object($this->queues[$queueSpec['name']]) && empty($queueSpec['reset'])) {
104 return $this->queues[$queueSpec['name']];
105 }
106
107 $queue = $this->instantiateQueueObject($queueSpec);
108 $exists = $queue->existsQueue();
109 if (!$exists) {
110 $queue->createQueue();
111 }
112 elseif (@$queueSpec['reset']) {
113 $queue->deleteQueue();
114 $queue->createQueue();
115 }
116 else {
117 $queue->loadQueue();
118 }
119 $this->queues[$queueSpec['name']] = $queue;
120 return $queue;
121 }
122
123 /**
4523a2f5
TO
124 * Look up an existing queue.
125 *
126 * @param array $queueSpec
127 * Array with keys:
128 * - type: string, required, e.g. "interactive", "immediate", "stomp",
129 * "beanstalk"
6a488035 130 * - name: string, required, e.g. "upgrade-tasks"
4523a2f5 131 * - (additional keys depending on the queue provider).
6a488035
TO
132 *
133 * @return CRM_Queue_Queue
134 */
4523a2f5 135 public function load($queueSpec) {
6a488035
TO
136 if (is_object($this->queues[$queueSpec['name']])) {
137 return $this->queues[$queueSpec['name']];
138 }
139 $queue = $this->instantiateQueueObject($queueSpec);
140 $queue->loadQueue();
141 $this->queues[$queueSpec['name']] = $queue;
142 return $queue;
143 }
144
145 /**
fe482240 146 * Convert a queue "type" name to a class name.
6a488035 147 *
4523a2f5
TO
148 * @param string $type
149 * E.g. "interactive", "immediate", "stomp", "beanstalk".
6a488035 150 *
4523a2f5
TO
151 * @return string
152 * Class-name
6a488035
TO
153 */
154 protected function getQueueClass($type) {
155 $type = preg_replace('/[^a-zA-Z0-9]/', '', $type);
156 $className = 'CRM_Queue_Queue_' . $type;
157 // FIXME: when used with class-autoloader, this may be unnecessary
158 if (!class_exists($className)) {
159 $classFile = 'CRM/Queue/Queue/' . $type . '.php';
160 require_once $classFile;
161 }
162 return $className;
163 }
164
165 /**
4523a2f5
TO
166 * @param array $queueSpec
167 * See create().
6a488035
TO
168 *
169 * @return CRM_Queue_Queue
170 */
171 protected function instantiateQueueObject($queueSpec) {
172 // note: you should probably never do anything else here
173 $class = new ReflectionClass($this->getQueueClass($queueSpec['type']));
174 return $class->newInstance($queueSpec);
175 }
96025800 176
6a488035 177}