PageRenderTime 377ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/redisconnector.php

http://github.com/gjedeer/celery-php
PHP | 233 lines | 106 code | 18 blank | 109 comment | 6 complexity | 96e8f309aafafbc5d86068c73e296094 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. <?php
  2. /**
  3. * This file contains a PHP client to Celery distributed task queue
  4. *
  5. * LICENSE: 2-clause BSD
  6. *
  7. * Copyright (c) 2014, flash286
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright notice, this
  14. * list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * The views and conclusions contained in the software and documentation are those
  31. * of the authors and should not be interpreted as representing official policies,
  32. * either expressed or implied, of the FreeBSD Project.
  33. *
  34. * @link https://github.com/flash286/celery-php
  35. * @link https://github.com/gjedeer/celery-php
  36. *
  37. * @package celery-php
  38. * @license http://opensource.org/licenses/bsd-license.php 2-clause BSD
  39. * @author flash286
  40. * @author GDR! <gdr@go2.pl>
  41. */
  42. /**
  43. * Created by PhpStorm.
  44. * User: nikolas
  45. * Date: 01.04.14
  46. * Time: 15:22
  47. */
  48. Predis\Autoloader::register();
  49. /**
  50. * Driver for predis - pure PHP implementation of the Redis protocol
  51. * composer require predis/predis:dev-master
  52. * @link https://github.com/nrk/predis
  53. * @package celery-php
  54. */
  55. class RedisConnector extends AbstractAMQPConnector {
  56. public $content_type = 'application/json';
  57. public $celery_result_prefix = 'celery-task-meta-';
  58. /**
  59. * Return headers used sent to Celery
  60. * Override this function to set custom headers
  61. */
  62. protected function GetHeaders()
  63. {
  64. return array();
  65. }
  66. /**
  67. * Prepare the message sent to Celery
  68. */
  69. protected function GetMessage($task)
  70. {
  71. $result = Array();
  72. $result['body'] = base64_encode($task);
  73. $result['headers'] = $this->GetHeaders();
  74. $result['content-type'] = $this->content_type;
  75. $result['content-encoding'] = 'binary';
  76. return $result;
  77. }
  78. /**
  79. * Return preferred delivery mode
  80. */
  81. protected function GetDeliveryMode()
  82. {
  83. /*
  84. * http://celery.readthedocs.org/en/latest/userguide/optimizing.html#using-transient-queues
  85. * 1 - will not be written to disk
  86. * 2 - can be written to disk
  87. */
  88. return 2;
  89. }
  90. /**
  91. * Convert the message dictionary to string
  92. * Override this function to use non-JSON serialization
  93. */
  94. protected function ToStr($var)
  95. {
  96. return json_encode($var);
  97. }
  98. /**
  99. * Convert the message string to dictionary
  100. * Override this function to use non-JSON serialization
  101. */
  102. protected function ToDict($raw_json)
  103. {
  104. return json_decode($raw_json, TRUE);
  105. }
  106. /**
  107. * Post the message to Redis
  108. * This function implements the AbstractAMQPConnector interface
  109. */
  110. public function PostToExchange($connection, $details, $task, $params)
  111. {
  112. $connection = $this->Connect($connection);
  113. $body = json_decode($task, true);
  114. $message = $this->GetMessage($task);
  115. $message['properties'] = Array(
  116. 'body_encoding' => 'base64',
  117. 'reply_to' => $body['id'],
  118. 'delivery_info' => Array(
  119. 'priority' => 0,
  120. 'routing_key' => $details['binding'],
  121. 'exchange' => $details['exchange'],
  122. ),
  123. 'delivery_mode' => $this->GetDeliveryMode(),
  124. 'delivery_tag' => $body['id']
  125. );
  126. $connection->lPush($details['exchange'], $this->ToStr($message));
  127. return TRUE;
  128. }
  129. /**
  130. * Initialize connection on a given connection object
  131. * This function implements the AbstractAMQPConnector interface
  132. * @return NULL
  133. */
  134. public function Connect($connection)
  135. {
  136. if ($connection->isConnected())
  137. {
  138. return $connection;
  139. }
  140. else
  141. {
  142. $connection->connect();
  143. return $connection;
  144. }
  145. }
  146. /**
  147. * Return the result queue name for a given task ID
  148. * @param string $task_id
  149. * @return string
  150. */
  151. protected function GetResultKey($task_id)
  152. {
  153. return sprintf("%s%s", $this->celery_result_prefix, $task_id);
  154. }
  155. /**
  156. * Clean up after reading the message body
  157. * @param object $connection Predis\Client connection object returned by GetConnectionObject()
  158. * @param string $task_id
  159. * @return bool
  160. */
  161. protected function FinalizeResult($connection, $task_id)
  162. {
  163. if ($connection->exists($this->GetResultKey($task_id)))
  164. {
  165. $connection->del($this->GetResultKey($task_id));
  166. return true;
  167. }
  168. return false;
  169. }
  170. /**
  171. * Return result of task execution for $task_id
  172. * @param object $connection Predis\Client connection object returned by GetConnectionObject()
  173. * @param string $task_id Celery task identifier
  174. * @param int $expire Unused in Redis
  175. * @param boolean $removeMessageFromQueue whether to remove message from queue
  176. * @return array|bool array('body' => JSON-encoded message body, 'complete_result' => library-specific message object)
  177. * or false if result not ready yet
  178. */
  179. public function GetMessageBody($connection, $task_id, $expire=0, $removeMessageFromQueue=true)
  180. {
  181. $result = $connection->get($this->GetResultKey($task_id));
  182. if ($result)
  183. {
  184. $redis_result = $this->ToDict($result, true);
  185. $result = Array(
  186. 'complete_result' => $redis_result,
  187. 'body' => json_encode($redis_result)
  188. );
  189. if ($removeMessageFromQueue)
  190. {
  191. $this->FinalizeResult($connection, $task_id);
  192. }
  193. return $result;
  194. }
  195. else
  196. {
  197. return false;
  198. }
  199. }
  200. /**
  201. * Return Predis\Client connection object passed to all other calls
  202. * @param array $details Array of connection details
  203. * @return object
  204. */
  205. function GetConnectionObject($details) {
  206. $connect = new Predis\Client(Array(
  207. 'scheme' => 'tcp',
  208. 'host' => $details['host'],
  209. 'port' => $details['port'],
  210. 'database' => $details['vhost'],
  211. 'password' => empty($details['password']) ? null : $details['password']
  212. ));
  213. return $connect;
  214. }
  215. }