xing-gearman-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ ?>