Merge pull request #3837 from eileenmcnaughton/CRM-15113
[civicrm-core.git] / CRM / Queue / Service.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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 +--------------------------------------------------------------------+
26 */
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();
43 * if (my_process($item->data)) {
44 * $myMessage->deleteItem();
45 * } else {
46 * $myMessage->releaseItem();
47 * }
48 * @endcode
49 */
50 class CRM_Queue_Service {
51
52 static $_singleton;
53
54 /**
55 * FIXME: Singleton pattern should be removed when dependency-injection
56 * becomes available.
57 *
58 * @param $forceNew bool
59 */
60 static function &singleton($forceNew = FALSE) {
61 if ($forceNew || !self::$_singleton) {
62 self::$_singleton = new CRM_Queue_Service();
63 }
64 return self::$_singleton;
65 }
66
67 /**
68 * @var array(queueName => CRM_Queue_Queue)
69 */
70 var $queues;
71 function __construct() {
72 $this->queues = array();
73 }
74
75 /**
76 *
77 * @param $queueSpec, array with keys:
78 * - type: string, required, e.g. "interactive", "immediate", "stomp", "beanstalk"
79 * - name: string, required, e.g. "upgrade-tasks"
80 * - reset: bool, optional; if a queue is found, then it should be flushed; default to TRUE
81 * - (additional keys depending on the queue provider)
82 *
83 * @return CRM_Queue_Queue
84 */
85 function create($queueSpec) {
86 if (@is_object($this->queues[$queueSpec['name']]) && empty($queueSpec['reset'])) {
87 return $this->queues[$queueSpec['name']];
88 }
89
90 $queue = $this->instantiateQueueObject($queueSpec);
91 $exists = $queue->existsQueue();
92 if (!$exists) {
93 $queue->createQueue();
94 }
95 elseif (@$queueSpec['reset']) {
96 $queue->deleteQueue();
97 $queue->createQueue();
98 }
99 else {
100 $queue->loadQueue();
101 }
102 $this->queues[$queueSpec['name']] = $queue;
103 return $queue;
104 }
105
106 /**
107 *
108 * @param $queueSpec, array with keys:
109 * - type: string, required, e.g. "interactive", "immediate", "stomp", "beanstalk"
110 * - name: string, required, e.g. "upgrade-tasks"
111 * - (additional keys depending on the queue provider)
112 *
113 * @return CRM_Queue_Queue
114 */
115 function load($queueSpec) {
116 if (is_object($this->queues[$queueSpec['name']])) {
117 return $this->queues[$queueSpec['name']];
118 }
119 $queue = $this->instantiateQueueObject($queueSpec);
120 $queue->loadQueue();
121 $this->queues[$queueSpec['name']] = $queue;
122 return $queue;
123 }
124
125 /**
126 * Convert a queue "type" name to a class name
127 *
128 * @param $type string, e.g. "interactive", "immediate", "stomp", "beanstalk"
129 *
130 * @return string, class-name
131 */
132 protected function getQueueClass($type) {
133 $type = preg_replace('/[^a-zA-Z0-9]/', '', $type);
134 $className = 'CRM_Queue_Queue_' . $type;
135 // FIXME: when used with class-autoloader, this may be unnecessary
136 if (!class_exists($className)) {
137 $classFile = 'CRM/Queue/Queue/' . $type . '.php';
138 require_once $classFile;
139 }
140 return $className;
141 }
142
143 /**
144 *
145 * @param $queueSpec array, see create()
146 *
147 * @return CRM_Queue_Queue
148 */
149 protected function instantiateQueueObject($queueSpec) {
150 // note: you should probably never do anything else here
151 $class = new ReflectionClass($this->getQueueClass($queueSpec['type']));
152 return $class->newInstance($queueSpec);
153 }
154 }
155