xing-gearman-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,410 @@
1
+ <?php
2
+
3
+ /**
4
+ * Interface for Danga's Gearman job scheduling system
5
+ *
6
+ * PHP version 5.1.0+
7
+ *
8
+ * LICENSE: This source file is subject to the New BSD license that is
9
+ * available through the world-wide-web at the following URI:
10
+ * http://www.opensource.org/licenses/bsd-license.php. If you did not receive
11
+ * a copy of the New BSD License and are unable to obtain it through the web,
12
+ * please send a note to license@php.net so we can mail you a copy immediately.
13
+ *
14
+ * @category Net
15
+ * @package Net_Gearman
16
+ * @author Joe Stump <joe@joestump.net>
17
+ * @copyright 2007-2008 Digg.com, Inc.
18
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
19
+ * @version CVS: $Id$
20
+ * @link http://pear.php.net/package/Net_Gearman
21
+ * @link http://www.danga.com/gearman/
22
+ */
23
+
24
+ require_once 'Net/Gearman/Exception.php';
25
+
26
+ /**
27
+ * The base connection class
28
+ *
29
+ * @category Net
30
+ * @package Net_Gearman
31
+ * @author Joe Stump <joe@joestump.net>
32
+ * @copyright 2007-2008 Digg.com, Inc.
33
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
34
+ * @link http://www.danga.com/gearman/
35
+ */
36
+ class Net_Gearman_Connection
37
+ {
38
+ /**
39
+ * A list of valid Gearman commands
40
+ *
41
+ * This is a list of valid Gearman commands (the key of the array), their
42
+ * integery type (first key in second array) used in the binary header, and
43
+ * the arguments / order of arguments to send/receive.
44
+ *
45
+ * @var array $commands
46
+ * @see Net_Gearman_Connection::$magic
47
+ * @see Net_Gearman_Connection::connect()
48
+ */
49
+ static protected $commands = array(
50
+ 'can_do' => array(1, array('func')),
51
+ 'can_do_timeout' => array(23, array('func', 'timeout')),
52
+ 'cant_do' => array(2, array('func')),
53
+ 'reset_abilities' => array(3, array()),
54
+ 'set_client_id' => array(22, array('client_id')),
55
+ 'pre_sleep' => array(4, array()),
56
+ 'noop' => array(6, array()),
57
+ 'submit_job' => array(7, array('func', 'uniq', 'arg')),
58
+ 'submit_job_high' => array(21, array('func', 'uniq', 'arg')),
59
+ 'submit_job_bg' => array(18, array('func', 'uniq', 'arg')),
60
+ 'job_created' => array(8, array('handle')),
61
+ 'grab_job' => array(9, array()),
62
+ 'no_job' => array(10, array()),
63
+ 'job_assign' => array(11, array('handle', 'func', 'arg')),
64
+ 'work_status' => array(12, array('handle', 'numerator', 'denominator')),
65
+ 'work_complete' => array(13, array('handle', 'result')),
66
+ 'work_fail' => array(14, array('handle')),
67
+ 'get_status' => array(15, array('handle')),
68
+ 'status_res' => array(20, array('handle', 'known', 'running', 'numerator', 'denominator')),
69
+ 'echo_req' => array(16, array('text')),
70
+ 'echo_res' => array(17, array('text')),
71
+ 'error' => array(19, array('err_code', 'err_text')),
72
+ 'all_yours' => array(24, array())
73
+ );
74
+
75
+ /**
76
+ * The reverse of Net_Gearman_Connection::$commands
77
+ *
78
+ * This is the same as the Net_Gearman_Connection::$commands array only
79
+ * it's keyed by the magic (integer value) value of the command.
80
+ *
81
+ * @var array $magic
82
+ * @see Net_Gearman_Connection::$commands
83
+ * @see Net_Gearman_Connection::connect()
84
+ */
85
+ static protected $magic = array();
86
+
87
+ /**
88
+ * Tasks waiting for a handle
89
+ *
90
+ * Tasks are popped onto this queue as they're submitted so that they can
91
+ * later be popped off of the queue once a handle has been assigned via
92
+ * the job_created command.
93
+ *
94
+ * @access public
95
+ * @var array $waiting
96
+ * @static
97
+ */
98
+ static public $waiting = array();
99
+
100
+ /**
101
+ * Is PHP's multibyte overload turned on?
102
+ *
103
+ * @var integer $multiByteSupport
104
+ */
105
+ static protected $multiByteSupport = null;
106
+
107
+ /**
108
+ * Constructor
109
+ *
110
+ * @return void
111
+ */
112
+ final private function __construct()
113
+ {
114
+ // Don't allow this class to be instantiated
115
+ }
116
+
117
+ /**
118
+ * Connect to Gearman
119
+ *
120
+ * Opens the socket to the Gearman Job server. It throws an exception if
121
+ * a socket error occurs. Also populates Net_Gearman_Connection::$magic.
122
+ *
123
+ * @param string $host e.g. 127.0.0.1 or 127.0.0.1:7003
124
+ * @param int $timeout Timeout in milliseconds
125
+ *
126
+ * @return resource A connection to a Gearman server
127
+ * @throws Net_Gearman_Exception when it can't connect to server
128
+ * @see Net_Gearman_Connection::$waiting
129
+ * @see Net_Gearman_Connection::$magic
130
+ * @see Net_Gearman_Connection::$commands
131
+ */
132
+ static public function connect($host, $timeout = 2000)
133
+ {
134
+ if (!count(self::$magic)) {
135
+ foreach (self::$commands as $cmd => $i) {
136
+ self::$magic[$i[0]] = array($cmd, $i[1]);
137
+ }
138
+ }
139
+
140
+ $err = '';
141
+ $errno = 0;
142
+ $port = 7003;
143
+
144
+ if (strpos($host, ':')) {
145
+ list($host, $port) = explode(':', $host);
146
+ }
147
+
148
+ $start = microtime(true);
149
+ do {
150
+ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
151
+ @socket_connect($socket, $host, $port);
152
+ $errorCode = socket_last_error($socket);
153
+
154
+ socket_set_nonblock($socket);
155
+ socket_set_option($socket, SOL_TCP, 1, 1);
156
+ $timeLeft = ((microtime(true) - $start) * 1000);
157
+ } while (!is_resource($socket) && $timeLeft < $timeout);
158
+
159
+ if ($errorCode == 111) {
160
+ throw new Net_Gearman_Exception("Can't connect to server");
161
+ }
162
+
163
+ self::$waiting[(int)$socket] = array();
164
+ return $socket;
165
+ }
166
+
167
+ /**
168
+ * Send a command to Gearman
169
+ *
170
+ * This is the command that takes the string version of the command you
171
+ * wish to run (e.g. 'can_do', 'grab_job', etc.) along with an array of
172
+ * parameters (in key value pairings) and packs it all up to send across
173
+ * the socket.
174
+ *
175
+ * @param resource $socket The socket to send the command to
176
+ * @param string $command Command to send (e.g. 'can_do')
177
+ * @param array $params Params to send
178
+ *
179
+ * @see Net_Gearman_Connection::$commands, Net_Gearman_Connection::$socket
180
+ * @return boolean
181
+ * @throws Net_Gearman_Exception on invalid command or unable to write
182
+ */
183
+ static public function send($socket, $command, array $params = array())
184
+ {
185
+ if (!isset(self::$commands[$command])) {
186
+ throw new Net_Gearman_Exception('Invalid command: ' . $command);
187
+ }
188
+
189
+ $data = array();
190
+ foreach (self::$commands[$command][1] as $field) {
191
+ if (isset($params[$field])) {
192
+ $data[] = $params[$field];
193
+ }
194
+ }
195
+
196
+ $d = implode("\x00", $data);
197
+
198
+ $cmd = "\0REQ" . pack("NN",
199
+ self::$commands[$command][0],
200
+ self::stringLength($d)) . $d;
201
+
202
+ $cmdLength = self::stringLength($cmd);
203
+ $written = 0;
204
+ $error = false;
205
+ do {
206
+ $check = @socket_write($socket,
207
+ self::subString($cmd, $written, $cmdLength),
208
+ $cmdLength);
209
+
210
+ if ($check === false) {
211
+ if (socket_last_error($socket) == SOCKET_EAGAIN or
212
+ socket_last_error($socket) == SOCKET_EWOULDBLOCK or
213
+ socket_last_error($socket) == SOCKET_EINPROGRESS)
214
+ {
215
+ // skip this is okay
216
+ }
217
+ else
218
+ {
219
+ $error = true;
220
+ break;
221
+ }
222
+ }
223
+
224
+ $written += (int)$check;
225
+ } while ($written < $cmdLength);
226
+
227
+ if ($error === true) {
228
+ throw new Net_Gearman_Exception(
229
+ 'Could not write command to socket'
230
+ );
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Read command from Gearman
236
+ *
237
+ * @param resource $socket The socket to read from
238
+ *
239
+ * @see Net_Gearman_Connection::$magic
240
+ * @return array Result read back from Gearman
241
+ * @throws Net_Gearman_Exception connection issues or invalid responses
242
+ */
243
+ static public function read($socket)
244
+ {
245
+ $header = '';
246
+ do {
247
+ $buf = socket_read($socket, 12 - self::stringLength($header));
248
+ $header .= $buf;
249
+ } while ($buf !== false &&
250
+ $buf !== '' && self::stringLength($header) < 12);
251
+
252
+ if ($buf === '') {
253
+ throw new Net_Gearman_Exception("Connection was reset");
254
+ }
255
+
256
+ if (self::stringLength($header) == 0) {
257
+ return array();
258
+ }
259
+ $resp = @unpack('a4magic/Ntype/Nlen', $header);
260
+
261
+ if (!count($resp) == 3) {
262
+ throw new Net_Gearman_Exception('Received an invalid response');
263
+ }
264
+
265
+ if (!isset(self::$magic[$resp['type']])) {
266
+ throw new Net_Gearman_Exception(
267
+ 'Invalid response magic returned: ' . $resp['type']
268
+ );
269
+ }
270
+
271
+ $return = array();
272
+ if ($resp['len'] > 0) {
273
+ $data = '';
274
+ while (self::stringLength($data) < $resp['len']) {
275
+ $data .= socket_read($socket, $resp['len'] - self::stringLength($data));
276
+ }
277
+
278
+ $d = explode("\x00", $data);
279
+ foreach (self::$magic[$resp['type']][1] as $i => $a) {
280
+ $return[$a] = $d[$i];
281
+ }
282
+ }
283
+
284
+ $function = self::$magic[$resp['type']][0];
285
+ if ($function == 'error') {
286
+ if (!self::stringLength($return['err_text'])) {
287
+ $return['err_text'] = 'Unknown error; see error code.';
288
+ }
289
+
290
+ throw new Net_Gearman_Exception(
291
+ $return['err_text'], $return['err_code']
292
+ );
293
+ }
294
+
295
+ return array('function' => self::$magic[$resp['type']][0],
296
+ 'type' => $resp['type'],
297
+ 'data' => $return);
298
+ }
299
+
300
+ /**
301
+ * Blocking socket read
302
+ *
303
+ * @param resource $socket The socket to read from
304
+ * @param float $timeout The timeout for the read
305
+ *
306
+ * @throws Net_Gearman_Exception on timeouts
307
+ * @return array
308
+ */
309
+ static public function blockingRead($socket, $timeout = 500)
310
+ {
311
+ static $cmds = array();
312
+
313
+ $tv_sec = floor(($timeout % 1000));
314
+ $tv_usec = ($timeout * 1000);
315
+
316
+ $start = microtime(true);
317
+ while (count($cmds) == 0) {
318
+ if (((microtime(true) - $start) * 1000) > $timeout) {
319
+ throw new Net_Gearman_Exception('Blocking read timed out');
320
+ }
321
+
322
+ $write = null;
323
+ $except = null;
324
+ $read = array($socket);
325
+
326
+ socket_select($read, $write, $except, $tv_sec, $tv_usec);
327
+ foreach ($read as $s) {
328
+ $cmds[] = Net_Gearman_Connection::read($s);
329
+ }
330
+ }
331
+
332
+ return array_shift($cmds);
333
+ }
334
+
335
+ /**
336
+ * Close the connection
337
+ *
338
+ * @param resource $socket The connection/socket to close
339
+ *
340
+ * @return void
341
+ */
342
+ static public function close($socket)
343
+ {
344
+ if (is_resource($socket)) {
345
+ socket_close($socket);
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Are we connected?
351
+ *
352
+ * @param resource $conn The connection/socket to check
353
+ *
354
+ * @return boolean False if we aren't connected
355
+ */
356
+ static public function isConnected($conn)
357
+ {
358
+ return (is_null($conn) !== true &&
359
+ is_resource($conn) === true &&
360
+ strtolower(get_resource_type($conn)) == 'socket');
361
+ }
362
+
363
+ /**
364
+ * Determine if we should use mb_strlen or stock strlen
365
+ *
366
+ * @param string $value The string value to check
367
+ *
368
+ * @return integer Size of string
369
+ * @see Net_Gearman_Connection::$multiByteSupport
370
+ */
371
+ static public function stringLength($value)
372
+ {
373
+ if (is_null(self::$multiByteSupport)) {
374
+ self::$multiByteSupport = intval(ini_get('mbstring.func_overload'));
375
+ }
376
+
377
+ if (self::$multiByteSupport & 2) {
378
+ return mb_strlen($value, '8bit');
379
+ } else {
380
+ return strlen($value);
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Multibyte substr() implementation
386
+ *
387
+ * @param string $str The string to substr()
388
+ * @param integer $start The first position used
389
+ * @param integer $length The maximum length of the returned string
390
+ *
391
+ * @return string Portion of $str specified by $start and $length
392
+ * @see Net_Gearman_Connection::$multiByteSupport
393
+ * @link http://us3.php.net/mb_substr
394
+ * @link http://us3.php.net/substr
395
+ */
396
+ static public function subString($str, $start, $length)
397
+ {
398
+ if (is_null(self::$multiByteSupport)) {
399
+ self::$multiByteSupport = intval(ini_get('mbstring.func_overload'));
400
+ }
401
+
402
+ if (self::$multiByteSupport & 2) {
403
+ return mb_substr($str, $start, $length, '8bit');
404
+ } else {
405
+ return substr($str, $start, $length);
406
+ }
407
+ }
408
+ }
409
+
410
+ ?>
@@ -0,0 +1,42 @@
1
+ <?php
2
+
3
+ /**
4
+ * Interface for Danga's Gearman job scheduling system
5
+ *
6
+ * PHP version 5.1.0+
7
+ *
8
+ * LICENSE: This source file is subject to the New BSD license that is
9
+ * available through the world-wide-web at the following URI:
10
+ * http://www.opensource.org/licenses/bsd-license.php. If you did not receive
11
+ * a copy of the New BSD License and are unable to obtain it through the web,
12
+ * please send a note to license@php.net so we can mail you a copy immediately.
13
+ *
14
+ * @category Net
15
+ * @package Net_Gearman
16
+ * @author Joe Stump <joe@joestump.net>
17
+ * @copyright 2007-2008 Digg.com, Inc.
18
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
19
+ * @version CVS: $Id$
20
+ * @link http://pear.php.net/package/Net_Gearman
21
+ * @link http://www.danga.com/gearman/
22
+ */
23
+
24
+ require_once 'PEAR/Exception.php';
25
+
26
+ /**
27
+ * Exception class for Net_Gearman
28
+ *
29
+ * @category Net
30
+ * @package Net_Gearman
31
+ * @author Joe Stump <joe@joestump.net>
32
+ * @copyright 2007-2008 Digg.com, Inc.
33
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
34
+ * @link http://www.danga.com/gearman/
35
+ * @see PEAR_Exception
36
+ */
37
+ class Net_Gearman_Exception extends PEAR_Exception
38
+ {
39
+
40
+ }
41
+
42
+ ?>
@@ -0,0 +1,135 @@
1
+ <?php
2
+
3
+ /**
4
+ * Interface for Danga's Gearman job scheduling system
5
+ *
6
+ * PHP version 5.1.0+
7
+ *
8
+ * LICENSE: This source file is subject to the New BSD license that is
9
+ * available through the world-wide-web at the following URI:
10
+ * http://www.opensource.org/licenses/bsd-license.php. If you did not receive
11
+ * a copy of the New BSD License and are unable to obtain it through the web,
12
+ * please send a note to license@php.net so we can mail you a copy immediately.
13
+ *
14
+ * @category Net
15
+ * @package Net_Gearman
16
+ * @author Joe Stump <joe@joestump.net>
17
+ * @copyright 2007-2008 Digg.com, Inc.
18
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
19
+ * @version CVS: $Id$
20
+ * @link http://pear.php.net/package/Net_Gearman
21
+ * @link http://www.danga.com/gearman/
22
+ */
23
+
24
+ require_once 'Net/Gearman/Job/Exception.php';
25
+
26
+ /**
27
+ * Base job class for all Gearman jobs
28
+ *
29
+ * @category Net
30
+ * @package Net_Gearman
31
+ * @author Joe Stump <joe@joestump.net>
32
+ * @copyright 2007-2008 Digg.com, Inc.
33
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
34
+ * @link http://www.danga.com/gearman/
35
+ * @see Net_Gearman_Job_Common, Net_Gearman_Worker
36
+ */
37
+ abstract class Net_Gearman_Job_Common
38
+ {
39
+ /**
40
+ * Gearman job handle
41
+ *
42
+ * @var string $handle
43
+ */
44
+ protected $handle = '';
45
+
46
+ /**
47
+ * Connection to Gearman
48
+ *
49
+ * @var resource $conn
50
+ * @see Net_Gearman_Connection
51
+ */
52
+ protected $conn = null;
53
+
54
+ /**
55
+ * Constructor
56
+ *
57
+ * @param resource $conn Connection to communicate with
58
+ * @param string $handle Job ID / handle for this job
59
+ *
60
+ * @return void
61
+ */
62
+ public function __construct($conn, $handle)
63
+ {
64
+ $this->conn = $conn;
65
+ $this->handle = $handle;
66
+ }
67
+
68
+ /**
69
+ * Run your job here
70
+ *
71
+ * @param array $arg Arguments passed from the client
72
+ *
73
+ * @return void
74
+ * @throws Net_Gearman_Exception
75
+ */
76
+ abstract public function run($arg);
77
+
78
+ /**
79
+ * Update Gearman with your job's status
80
+ *
81
+ * @param integer $numerator The numerator (e.g. 1)
82
+ * @param integer $denominator The denominator (e.g. 100)
83
+ *
84
+ * @return void
85
+ * @see Net_Gearman_Connection::send()
86
+ */
87
+ public function status($numerator, $denominator)
88
+ {
89
+ Net_Gearman_Connection::send($this->conn, 'work_status', array(
90
+ 'handle' => $this->handle,
91
+ 'numerator' => $numerator,
92
+ 'denominator' => $denominator
93
+ ));
94
+ }
95
+
96
+ /**
97
+ * Mark your job as complete with its status
98
+ *
99
+ * Net_Gearman communicates between the client and jobs in JSON. The main
100
+ * benefit of this is that we can send fairly complex data types between
101
+ * different languages. You should always pass an array as the result to
102
+ * this function.
103
+ *
104
+ * @param array $result Result of your job
105
+ *
106
+ * @return void
107
+ * @see Net_Gearman_Connection::send()
108
+ */
109
+ public function complete(array $result)
110
+ {
111
+ Net_Gearman_Connection::send($this->conn, 'work_complete', array(
112
+ 'handle' => $this->handle,
113
+ 'result' => json_encode($result)
114
+ ));
115
+ }
116
+
117
+ /**
118
+ * Mark your job as failing
119
+ *
120
+ * If your job fails for some reason (e.g. a query fails) you need to run
121
+ * this function and exit from your run() method. This will tell Gearman
122
+ * (and the client by proxy) that the job has failed.
123
+ *
124
+ * @return void
125
+ * @see Net_Gearman_Connection::send()
126
+ */
127
+ public function fail()
128
+ {
129
+ Net_Gearman_Connection::send($this->conn, 'work_fail', array(
130
+ 'handle' => $this->handle
131
+ ));
132
+ }
133
+ }
134
+
135
+ ?>
@@ -0,0 +1,45 @@
1
+ <?php
2
+
3
+ /**
4
+ * Interface for Danga's Gearman job scheduling system
5
+ *
6
+ * PHP version 5.1.0+
7
+ *
8
+ * LICENSE: This source file is subject to the New BSD license that is
9
+ * available through the world-wide-web at the following URI:
10
+ * http://www.opensource.org/licenses/bsd-license.php. If you did not receive
11
+ * a copy of the New BSD License and are unable to obtain it through the web,
12
+ * please send a note to license@php.net so we can mail you a copy immediately.
13
+ *
14
+ * @category Net
15
+ * @package Net_Gearman
16
+ * @author Joe Stump <joe@joestump.net>
17
+ * @copyright 2007-2008 Digg.com, Inc.
18
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
19
+ * @version CVS: $Id$
20
+ * @link http://pear.php.net/package/Net_Gearman
21
+ * @link http://www.danga.com/gearman/
22
+ */
23
+
24
+ require_once 'PEAR/Exception.php';
25
+
26
+ /**
27
+ * Exception class for Gearman jobs
28
+ *
29
+ * Your Gearman jobs should throw this from their run() method if they run
30
+ * into any kind of error.
31
+ *
32
+ * @category Net
33
+ * @package Net_Gearman
34
+ * @author Joe Stump <joe@joestump.net>
35
+ * @copyright 2007-2008 Digg.com, Inc.
36
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
37
+ * @link http://www.danga.com/gearman/
38
+ * @see Net_Gearman_Job_Common, Net_Gearman_Worker
39
+ */
40
+ class Net_Gearman_Job_Exception extends PEAR_Exception
41
+ {
42
+
43
+ }
44
+
45
+ ?>
@@ -0,0 +1,33 @@
1
+ <?php
2
+
3
+ /**
4
+ * Sum up a bunch of numbers
5
+ *
6
+ * @author Ladislav Martincik <ladislav.martincik@xing.com>
7
+ * @package Net_Gearman
8
+ */
9
+ class Net_Gearman_Job_Sleep extends Net_Gearman_Job_Common
10
+ {
11
+ /**
12
+ * Run the Sleep job
13
+ *
14
+ * @access public
15
+ * @param array $arg
16
+ * @return array
17
+ */
18
+ public function run($arg)
19
+ {
20
+ $seconds = $arg['seconds'];
21
+ echo $seconds;
22
+ while ($seconds > 0) {
23
+ print $seconds;
24
+ sleep(1);
25
+ $this->status($i, $seconds);
26
+ $seconds--;
27
+ }
28
+
29
+ return true;
30
+ }
31
+ }
32
+
33
+ ?>