PageRenderTime 35ms CodeModel.GetById 29ms app.highlight 3ms 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
  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
 49Predis\Autoloader::register();
 50
 51/**
 52 * Driver for predis - pure PHP implementation of the Redis protocol
 53 * composer require predis/predis:dev-master
 54 * @link https://github.com/nrk/predis
 55 * @package celery-php
 56 */
 57class RedisConnector extends AbstractAMQPConnector {
 58
 59    public $content_type = 'application/json';
 60
 61    public $celery_result_prefix = 'celery-task-meta-';
 62
 63	/**
 64	 * Return headers used sent to Celery
 65	 * Override this function to set custom headers
 66	 */
 67	protected function GetHeaders() 
 68	{
 69        return array();
 70    }
 71
 72	/**
 73	 * Prepare the message sent to Celery
 74	 */
 75	protected function GetMessage($task) 
 76	{
 77        $result = Array();
 78        $result['body'] = base64_encode($task);
 79        $result['headers'] = $this->GetHeaders();
 80        $result['content-type'] = $this->content_type;
 81        $result['content-encoding'] = 'binary';
 82        return $result;
 83    }
 84
 85	/**
 86	 * Return preferred delivery mode
 87	 */
 88	protected function GetDeliveryMode() 
 89	{
 90	    /* 
 91		 * http://celery.readthedocs.org/en/latest/userguide/optimizing.html#using-transient-queues
 92		 * 1 - will not be written to disk
 93		 * 2 - can be written to disk
 94		 */
 95        return 2;
 96    }
 97
 98	/**
 99	 * Convert the message dictionary to string
100	 * Override this function to use non-JSON serialization
101	 */
102	protected function ToStr($var)
103	{
104        return json_encode($var);
105    }
106
107	/**
108	 * Convert the message string to dictionary
109	 * Override this function to use non-JSON serialization
110	 */
111	protected function ToDict($raw_json) 
112	{
113        return json_decode($raw_json, TRUE);
114    }
115
116	/**
117	 * Post the message to Redis
118	 * This function implements the AbstractAMQPConnector interface
119	 */
120	public function PostToExchange($connection, $details, $task, $params) 
121	{
122        $connection = $this->Connect($connection);
123        $body = json_decode($task, true);
124        $message = $this->GetMessage($task);
125        $message['properties'] = Array(
126            'body_encoding' => 'base64',
127            'reply_to' => $body['id'],
128            'delivery_info' => Array(
129                'priority' => 0,
130                'routing_key' => $details['binding'],
131                'exchange' => $details['exchange'],
132            ),
133            'delivery_mode' => $this->GetDeliveryMode(),
134            'delivery_tag'  => $body['id']
135        );
136        $connection->lPush($details['exchange'], $this->ToStr($message));
137
138		return TRUE;
139    }
140
141	/**
142	 * Initialize connection on a given connection object
143	 * This function implements the AbstractAMQPConnector interface
144	 * @return NULL
145	 */
146	public function Connect($connection) 
147	{
148	    if ($connection->isConnected()) 
149	    {
150            return $connection;
151		} 
152		else 
153		{
154            $connection->connect();
155            return $connection;
156        }
157    }
158
159	/**
160	 * Return the result queue name for a given task ID
161	 * @param string $task_id
162	 * @return string
163	 */
164	protected function GetResultKey($task_id) 
165	{
166        return sprintf("%s%s", $this->celery_result_prefix, $task_id);
167    }
168
169	/**
170	 * Clean up after reading the message body
171	 * @param object $connection Predis\Client connection object returned by GetConnectionObject()
172	 * @param string $task_id
173	 * @return bool
174	 */
175	protected function FinalizeResult($connection, $task_id) 
176	{
177		if ($connection->exists($this->GetResultKey($task_id))) 
178		{
179            $connection->del($this->GetResultKey($task_id));
180            return true;
181        }
182		
183		return false;
184    }
185
186	/**
187	 * Return result of task execution for $task_id
188	 * @param object $connection Predis\Client connection object returned by GetConnectionObject()
189	 * @param string $task_id Celery task identifier
190	 * @param int $expire Unused in Redis
191	 * @param boolean $removeMessageFromQueue whether to remove message from queue
192	 * @return array|bool array('body' => JSON-encoded message body, 'complete_result' => library-specific message object)
193	 * 			or false if result not ready yet
194	 */
195	public function GetMessageBody($connection, $task_id, $expire=0, $removeMessageFromQueue=true) 
196	{
197		$result = $connection->get($this->GetResultKey($task_id));
198		if ($result) 
199		{
200			$redis_result = $this->ToDict($result, true);
201			$result = Array(
202				'complete_result' => $redis_result,
203				'body' => json_encode($redis_result)
204			);
205			if ($removeMessageFromQueue) 
206			{
207				$this->FinalizeResult($connection, $task_id);
208			}
209
210			return $result;
211		}
212		else 
213		{
214			return false;
215		}
216	}
217
218	/**
219	 * Return Predis\Client connection object passed to all other calls
220	 * @param array $details Array of connection details
221	 * @return object
222	 */
223    function GetConnectionObject($details) {
224        $connect = new Predis\Client(Array(
225            'scheme' => 'tcp',
226            'host'   => $details['host'],
227            'port'   => $details['port'],
228            'database' => $details['vhost'],
229            'password' => empty($details['password']) ? null : $details['password']
230        ));
231        return $connect;
232    }
233}