Giter VIP home page Giter VIP logo

pheanstalk's Introduction

Pheanstalk

Latest Stable Version Total Downloads Scrutinizer Code Quality Code Coverage Build Status

Pheanstalk 5 is a pure PHP8.1+ client for use with beanstalkd workqueue versions 1.12 and later. In 2021 / 2022 / 2023 it was almost completely rewritten from scratch with the following goals in mind:

  • Fully typed
  • Passing the strict rule set for static analysis using PHPStan and Psalm
  • Splitting the different roles into separate parts

Usage Example

Producer

use Pheanstalk\Pheanstalk;
use Pheanstalk\Values\TubeName;

$pheanstalk = Pheanstalk::create('127.0.0.1');
$tube       = new TubeName('testtube');

// Queue a Job
$pheanstalk->useTube($tube);
$pheanstalk->put("job payload goes here\n");

$pheanstalk->useTube($tube);
$pheanstalk->put(
    data: json_encode(['test' => 'data'], JSON_THROW_ON_ERROR),
    priority: Pheanstalk::DEFAULT_PRIORITY,
    delay: 30,
    timeToRelease: 60
);

Consumer / Worker

use Pheanstalk\Pheanstalk;
use Pheanstalk\Values\TubeName;

$pheanstalk = Pheanstalk::create('127.0.0.1');
$tube       = new TubeName('testtube');

// we want jobs from 'testtube' only.
$pheanstalk->watch($tube);

// this hangs until a Job is produced.
$job = $pheanstalk->reserve();

try {
    $jobPayload = $job->getData();
    // do work.
    
    echo "Starting job with payload: {$jobPayload}\n";

    sleep(2);
    // If it's going to take a long time, periodically
    // tell beanstalk we're alive to stop it rescheduling the job.
    $pheanstalk->touch($job);
    sleep(2);

    // eventually we're done, delete job.
    $pheanstalk->delete($job);
}
catch(\Exception $e) {
    // handle exception.
    // and let some other worker retry.
    $pheanstalk->release($job); 
}

Running the tests

Make sure you have docker-compose installed.

> composer test

History

Pheanstalk 4

In 2018 Sam Mousa took on the responsibility of maintaining Pheanstalk.

Pheanstalk 4.0 drops support for older PHP versions. It contains the following changes (among other things):

  • Strict PHP type hinting
  • Value objects for Job IDs
  • Functions without side effects
  • Dropped support for persistent connections
  • Add support for multiple socket implementations (streams extension, socket extension, fsockopen)

Dropping support persistent connections

Persistent connections are a feature where a TCP connection is kept alive between different requests to reduce overhead from TCP connection set up. When reusing TCP connections we must always guarantee that the application protocol, in this case beanstalks' protocol is in a proper state. This is hard, and in some cases impossible; at the very least this means we must do some tests which cause roundtrips. Consider for example a connection that has just sent the command PUT 0 4000. The beanstalk server is now going to read 4000 bytes, but if the PHP script crashes during this write the next request get assigned this TCP socket. Now to reset the connection to a known state it used to subscribe to the default tube: use default. Since the beanstalk server is expecting 4000 bytes, it will just write this command to the job and wait for more bytes..

To prevent these kinds of issues the simplest solution is to not use persistent connections.

Dropped connection handling

Depending on the socket implementation used we might not be able to enable TCP keepalive. If we do not have TCP keepalive there is no way for us to detect dropped connections, the underlying OS may wait up to 15 minutes to decide that a TCP connection where no packets are being sent is disconnected. When using a socket implementation that supports read timeouts, like SocketSocket which uses the socket extension we use read and write timeouts to detect broken connections; the issue with the beanstalk protocol is that it allows for no packets to be sent for extended periods of time. Solutions are to either catch these connection exceptions and reconnect or use reserveWithTimeout() with a timeout that is less than the read / write timeouts.

Example code for a job runner could look like this (this is real production code):

use Pheanstalk\Pheanstalk;
use Pheanstalk\Values\TubeName;

interface Task {

}
interface TaskFactory {
    public function fromData(string $data): Task;
}
interface CommandBus {
    public function handle(Task $task): void;
}

function run(\Pheanstalk\PheanstalkSubscriber $pheanstalk, CommandBus $commandBus, TaskFactory $taskFactory): void
{
    /**
     * @phpstan-ignore-next-line
     */
    while (true) {
        $job = $pheanstalk->reserveWithTimeout(50);
        if (isset($job)) {
            try {

                $task = $taskFactory->fromData($job->getData());
                $commandBus->handle($task);
                echo "Deleting job: {$job->getId()}\n";
                $pheanstalk->delete($job);
            } catch (\Throwable $t) {
                echo "Burying job: {$job->getId()}\n";
                $pheanstalk->bury($job);
            }
        }
    }
}

Here connection errors will cause the process to exit (and be restarted by a task manager).

Functions with side effects

In version 4 functions with side effects have been removed, functions like putInTube internally did several things:

  1. Switch to the tube
  2. Put the job in the new tube

In this example, the tube changes meaning that the connection is now in a different state. This is not intuitive and forces any user of the connection to always switch / check the current tube. Another issue with this approach is that it is harder to deal with errors. If an exception occurs it is unclear whether we did or did not switch tube.

Migration to v4

A migration should in most cases be relatively simple:

  • Change the constructor, either use the static constructor, use a DI container to construct the dependencies, or manually instantiate them.
  • Change instances of reserve() with a timeout to reserveWithTimeout(int $timeout) since reserve() no longer accepts a timeout parameter.
  • Run your tests, or use a static analyzer to test for calls to functions that no longer exist.
  • Make sure that you handle connection exceptions (this is not new to V4, only in V4 you will get more of them due to the default usage of a socket implementation that has read / write timeouts).

Pheanstalk 3

Pheanstalk is a pure PHP 7.1+ client for the beanstalkd workqueue. It has been actively developed, and used in production by many, since late 2008.

Created by Paul Annesley, Pheanstalk is rigorously unit tested and written using encapsulated, maintainable object oriented design. Community feedback, bug reports and patches has led to a stable 1.0 release in 2010, a 2.0 release in 2013, and a 3.0 release in 2014.

Pheanstalk 3.0 introduces PHP namespaces, PSR-1 and PSR-2 coding standards, and PSR-4 autoloader standard.

beanstalkd up to the latest version 1.10 is supported. All commands and responses specified in the protocol documentation for beanstalkd 1.3 are implemented.

pheanstalk's People

Contributors

armetiz avatar davidgoodwin avatar gcatlin avatar grahamcampbell avatar henrycatalinismith avatar jbboehr avatar jimbojsb avatar le-oliver avatar leprechaun avatar mhor avatar mnapoli avatar mrjameshamilton avatar nikozen avatar noisebynorthwest avatar olafkarsten avatar panicoschr avatar pascalheidmann-check24 avatar pda avatar phansys avatar sammousa avatar samnela avatar scrutinizer-auto-fixer avatar slnpacifist avatar splotycode avatar sraka1 avatar srjlewis avatar taomin597715379 avatar thewunder avatar tuupke avatar vstm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pheanstalk's Issues

Clear tube command

Hello,

I wonder if there is a way to clean all the tube at once?

Thank you

Connection problem adding more 100k jobs to beanstalkd

Hi,

PHP does not close the connections properly i don't know, when I'm adding more 100k jobs to the queue with pheanstalk. I checked your code and made some changes on it, letting it use a "persistant" connection (keeping socket).

I cannnot attach files here, so if you want take a look at my changes, send me an email and I will provide you the changes :)

Regards,
Sven

compatibility with beanstalkd 1.3 ?

Hi there,

I'm trying to use current pheanstalk code (9bff1f2) against beanstalkd 1.3.

Is this supposed to work?

$ php runtests.php --with-server
All Tests
Exception 1!
Unexpected exception of type [Pheanstalk_Exception_ServerUnknownCommandException] with message [UNKNOWN_COMMAND in response to 'pause-tube test-pause-tube 1'] in [/home/gonzalo/src/class/pheanstalk/classes/Pheanstalk/Connection.php line 92]
    in testPauseTube
    in Pheanstalk_FacadeConnectionTest
    in /home/gonzalo/src/class/pheanstalk/tests/Pheanstalk/FacadeConnectionTest.php
FAILURES!!!
Test cases run: 10/10, Passes: 368, Failures: 0, Exceptions: 

Inconsistent handling of passed Jobs / JobId's

Passing of Job's and/or JobId's is a bit inconsistent.
Request: all job related commands either take a job object, or a job id.

Eg in:

class Pheanstalk_Command_StatsJobCommand
    extends Pheanstalk_Command_AbstractCommand
{
    // [...]
    public function __construct($job)
    {
        $this->_jobId = is_object($job) ? $job->getId() : $job;
    }

    public function getCommandLine()
    {
        return sprintf('stats-job %d', $this->_jobId);
    }

Versus:

class Pheanstalk_Command_BuryCommand
    extends Pheanstalk_Command_AbstractCommand
    implements Pheanstalk_ResponseParser
{
    // [...]
    public function __construct($job, $priority)
    {
        $this->_job = $job;
        $this->_priority = $priority;
    }

    // [...]
    public function getCommandLine()
    {
        return sprintf(
            'bury %d %d',
            $this->_job->getId(),
            $this->_priority

I've had not checked all commands yet, these I encountered just now.
Update: only statsjob seems to allow for jobid directly.

E_STRICT errors when running runtests.php

When I run runtests.php on my machine, I get the following four exceptions:

E_STRICT: Non-static method Pheanstalk_Socket_StreamFunctions::setInstance() should not be called statically, assuming $this from incompatible context in /home/henry/tmp/pheanstalk/tests/Pheanstalk/NativeSocketTest.php on line 22
E_STRICT: Non-static method Pheanstalk_Socket_StreamFunctions::unsetInstance() should not be called statically, assuming $this from incompatible context in /home/henry/tmp/pheanstalk/tests/Pheanstalk/NativeSocketTest.php on line 28
E_STRICT: Non-static method Pheanstalk_Socket_StreamFunctions::setInstance() should not be called statically, assuming $this from incompatible context in /home/henry/tmp/pheanstalk/tests/Pheanstalk/NativeSocketTest.php on line 22
E_STRICT: Non-static method Pheanstalk_Socket_StreamFunctions::unsetInstance() should not be called statically, assuming $this from incompatible context in /home/henry/tmp/pheanstalk/tests/Pheanstalk/NativeSocketTest.php on line 2

I've seen code with this in the past where it was being done this way for a reason, so I was hesitant to do something as presumptuous as a pull request. The patch for this is almost as trivial as the last one I submitted, and can be seen at https://github.com/h2s/pheanstalk/compare/strictcompliance. With that change in place, the tests pass with 0 exceptions on my machine.

My only concern is that it could potentially break backwards compatibility if there is any code out there that calls setInstance() or unsetInstance() on an instance of Pheanstalk_Socket_StreamFunctions rather than statically. This being the case, I'd understand if it seems safer to leave this as it is now. In that case, it might be prudent to remove E_STRICT from the error reporting level instead before running the tests.

Wrong strlen on mbstring overloaded environments

When using charsets like UTF-8 and overloading mbstring functions

php.ini:
default_charset = "utf-8"
mbstring.func_overload=7
mbstring.internal_encoding=utf-8

strlen counts the number of complete characters, but we need the number of single bytes in order to tell the beanstalk server how much data we are going to send with the put command.

mb_strlen($data, "latin1") should be used to force counting single bytes on any environment.

Stats() Command fails if Version isn't set

If beanstalkd doesn't have a version number (I just downloaded and compiled 1.4.3 and it doesn't) the stats command fails (because there is version).

I modified the config.h of beanstalkd, recompiled and stats now works fine. Pheanstalk should at least cope parsing a message with no version number.

See stack trace:

Fatal error: Uncaught exception 'Pheanstalk_Exception' with message 'YAML parse error for line: version: ' in /media/psf/pp/library/pheanstalk/classes/Pheanstalk/YamlResponseParser.php:62
Stack trace:
#0 /media/psf/pp/library/pheanstalk/classes/Pheanstalk/Connection.php(157): Pheanstalk_YamlResponseParser->parseResponse('OK 802', '---?current-job...')
#1 /media/psf/pp/library/pheanstalk/classes/Pheanstalk.php(395): Pheanstalk_Connection->dispatchCommand(Object(Pheanstalk_Command_StatsCommand))
#2 /media/psf/pp/library/pheanstalk/classes/Pheanstalk.php(329): Pheanstalk->_dispatch(Object(Pheanstalk_Command_StatsCommand))
#3 /media/psf/pp/library/pheanstalk/test.php(15): Pheanstalk->stats('testtube')
#4 {main}

thrown in /media/psf/pp/library/pheanstalk/classes/Pheanstalk/YamlResponseParser.php on line 62

No type hints in source

In no place a type hint is used, only phpdoc suggestions. This can cause problems later in the process when types are expected.

An example: Pheanstalk_Command_DeleteCommand sets a $job during __construct() without type hint. In Pheanstalk_Command_DeleteCommand::getCommandLine() a call to $this->_job->getId() is used. While I am able to set just a string as $job (Pheanstalk::delete('foo')), obviously this won't work.

Is this intentionally left out?

What's the plan for V2.0 ?

I've noticed there is some information in the master branch about the version 2.0 and the 2.0-rc1. What's the plan for this version?

Can you give feedback on issues that are open to know if we are following the idea you have about this library? There is issues open for more than a year now without comment.

Cheers,
Maxime

NativeSocket.php doesn't handle socket timeouts of existing connections

The NativeSocket.php class sets the socket timeout via socket_set_timeout.

In testing, we realized when a server crashed that the client didn't ever time out the existing connections. Upon inspecting the http://php.net/socket_set_timeout docs, we discovered that the code needs to check the socket_get_meta_data() function to see if the socket has timed out.

We propose the following patch to correct this:

    Index: Socket/NativeSocket.php
    ===================================================================
    --- Socket/NativeSocket.php     (revision 7)
    +++ Socket/NativeSocket.php     (working copy)
    @@ -36,7 +36,9 @@
             */
            public function write($data)
            {
    -               return fwrite($this->_socket, $data);
    +               $result = fwrite($this->_socket, $data);
    +               $this->checkTimedOut();
    +               return $result;
            }

            /* (non-phpdoc)
    @@ -44,7 +46,9 @@
             */
            public function read($length)
            {
    -               return fread($this->_socket, $length);
    +               $data = fread($this->_socket, $length);
    +               $this->checkTimedOut();
    +               return $data;
            }

            /* (non-phpdoc)
    @@ -60,9 +64,18 @@
                            {
                                    throw new Pheanstalk_Exception_ConnectionException(666, "Socket closed by server!");
                            }
    +                       $this->checkTimedOut();
                    }
                    while ($data === false);

                    return rtrim($data);
            }
    +
    +       protected function checkTimedOut() {
    +               $meta = stream_get_meta_data($this->_socket);
    +               if ($meta['timed_out']) {
    +                       throw new Pheanstalk_Exception_ConnectionException(666, "Socket timed out with server!");
    +
    +               }
    +       }
     }

Error when reading more than 8192 bytes

This maybe a (not so smart fix) for NativeSocket.php

/* (non-phpdoc)
 * @see Pheanstalk_Socket::write()
 */
public function write($data)
{
    //return fwrite($this->_socket, $data);

    $bytes_to_write = strlen($data);
    $bytes_written = 0;

    while ( $bytes_written < $bytes_to_write )
    {
        if ( $bytes_written == 0 ) {
            $rv = fwrite($this->_socket, $data);
        } else {
            $rv = fwrite($this->_socket, substr($data, $bytes_written));
        }

        if ( $rv === false || $rv == 0 )
        return( $bytes_written == 0 ? false : $bytes_written );

        $bytes_written += $rv;
    }

}

/* (non-phpdoc)
 * @see Pheanstalk_Socket::write()
 */
public function read($length)
{
    if ($length == 0) {
        return null;
    }
    if ($length <= 1024) {
        return fread($this->_socket, $length);
    }
    $length_to_read = 0;
    $data = '';
    for ($i = $length; $i > 0;$i = $i - 1024) {
        if ($i < 1024) {
            $data .= fread($this->_socket, $i);
        } else {
            $data .= fread($this->_socket, 1024);
        }
    }
    return $data;

}

Option to specify Default Tube

The current implementation creates an extra tube which is default tube and I can't find a good way to change it to whatever name I please other than changing the Hardcoded constant.

I suggest that while creating connection you should be able to pass the default tube name (optional) which will make pheanstalk watch that specific tube.

Let me know what you think,

Regards,
Munir

Socket error 13: Permission denied (connecting to localhost:11300) on CentOS 6.5 64bit

I encounter the problem of Socket error 13: Permission denied (connecting to localhost:11300) on apache on centos 6.5, i dont know if this is a linux problem or not.

prod.ERROR: exception 'Pheanstalk_Exception_ConnectionException' with message 'Socket error 13: Permission denied (connecting to localhost:11300)' in /var/www/html/vendor/pda/pheanstalk/classes/Pheanstalk/Socket/NativeSocket.php:35
Stack trace:
#0 /var/www/html/vendor/pda/pheanstalk/classes/Pheanstalk/Connection.php(164): Pheanstalk_Socket_NativeSocket->__construct('localhost', 11300, 2)
#1 /var/www/html/vendor/pda/pheanstalk/classes/Pheanstalk/Connection.php(72): Pheanstalk_Connection->_getSocket()
#2 /var/www/html/vendor/pda/pheanstalk/classes/Pheanstalk/Pheanstalk.php(372): Pheanstalk_Connection->dispatchCommand(Object(Pheanstalk_Command_PutCommand))
#3 /var/www/html/vendor/pda/pheanstalk/classes/Pheanstalk/Pheanstalk.php(219): Pheanstalk_Pheanstalk->_dispatch(Object(Pheanstalk_Command_PutCommand))

New PSR-0 Library no longer has getConnection() method

With the recent updates the $pheanstalk->getConnection() function has been removed, which breaks usage of the isServiceListening() method (among others).

If this was deliberate, why, and if not can it be added back in again please.

My implementation makes use of the getHost(), getPort() and isServiceListening() functions which are now no longer available.

The change this occurred in is: 412ab5b#L0L46

Documentation of Pheanstalk::release()

The documentation of Pheanstalk::release() appears to be incorrect.

Currently http://github.com/pda/pheanstalk/blob/master/classes/Pheanstalk.php#L250 says:

  Puts a job into a 'buried' state, revived only by 'kick' command.

This seems to be the same as the bury() command. I think it should be changed to something like:

 The release command puts a reserved job back into the ready queue (and marks
 its state as "ready") to be run by any client. It is normally used when the job
 fails because of a transitory error."

(from http://github.com/kr/beanstalkd/blob/master/doc/protocol.txt#L262 )

Pheanstalk does not reconnect to beanstalkd

In case we restart beanstalkd pheanstalk does not establish a new connection, just throws exception "Socket error 666: Socket closed by server!" several first times trying to get task from tube and then "fwrite() [function.fwrite]: send of 24 bytes failed with errno=10053". It seems to be better to try to silently reconnect to beanstalkd.

Why is PHP 5.2 required? Will it work on PHP v5.1.6?

I've got a CentOS VM running, and I installed beanstalkd 1.4.

I've checked out the pheanstalk code and run the unit tests, and everything passes. This VM is running PHP v5.1.6, which is the version that CentOS supports.

What things are in the pheanstalk code that may not work on 5.1.6?

Thanks,
.dave.

Pheanstalk adds jobs with the wrong data length?

I noticed today in a consumer I had written that I was getting errors like:

exception 'Pheanstalk_Exception_ClientException' with message 'Expected 2 bytes of CRLF after 7425 bytes of data' in /src/classes/Pheanstalk/Connection.php:106

and

exception 'Pheanstalk_Exception_ClientException' with message 'Expected 2 bytes of CRLF after 3300 bytes of data' in /src/classes/Pheanstalk/Connection.php:106

I should mention that if I continue to read on the socket past the specified data length I find more of my serialized array data.

These seem to happen somewhat frequently. My payload is simply a multi-dimensional PHP array. Any ideas?

Adding to QUEUE failed at first time.

Hi,

Thanks for your AWESOME beanstalkd php-client.
The issue i am facing is that,adding to queue fails at first time,afterwards it's working fine.
Any idea.

Thanks in advance.

check service availability gives a fatal error

Hi,
I download the library and was try to use it, with the guide provide, in the read me, I got an error ,
PHP Fatal error: Call to undefined method Pheanstalk_Pheanstalk::getConnection() in /var/www/projects/testing/beanstalkd/index.php on line 11

Pheanstalk is hard to extend

Because all properties and non-public methods are private instead of protected, it is challenging to extend Pheanstalk. Would you be opposed to making properties and non-public methods protected instead, or adding protected or public accessor methods? If so, I'll submit a pull request. Thanks

-Geoff

Put command getCommandLine() sprintf format type specifier

The beanstalkd protocol states that the priority is an unsigned int (up to 4294967295). Pheanstalk_Command_PutCommand->getCommandLine() (line 42) uses %d in the sprintf format string, which according to the PHP doc is '...presented as a (signed) decimal number'. As such, any priority over 2147483647 is formatted incorrectly. To correct this, the first %d in the sprintf just needs to change to %u. I would do this and submit the code but I'm completely unfamiliar with git and github.

Exception handling when connecting to beanstalk'd

I dont have beanstalk'd running but still i don't get any exception.

                $this->pheanstalk   = new Pheanstalk('127.0.0.1');
                $this->tube         = $tube;
                                print_r($this->pheanstalk);
            }
            catch (Exception $e) {
                throw new Exception();
                exit(1);
            }

The above code returns/prints

Pheanstalk Object ( [_connection:Pheanstalk:private] => Pheanstalk_Connection Object ( [_socket:Pheanstalk_Connection:private] => [_hostname:Pheanstalk_Connection:private] => 127.0.0.1 [_port:Pheanstalk_Connection:private] => 11300 [_connectTimeout:Pheanstalk_Connection:private] => 2 ) [_using:Pheanstalk:private] => default [_watching:Pheanstalk:private] => Array ( [default] => 1 ) )

If i do a put or reserveFromTube i get exception but not in the above case  why 

Pheanstalk needs maintainer(s)

Many people are using Pheanstalk, but I haven't been able to give it the attention it deserves.

I'd love to take on one or more maintainer (two sounds like a good number) to help push it forwards.

Anybody interested?

Let me know in what capacity you use Pheanstalk (e.g. for what purpose, at what company etc) [Optional. And be as vague or specific as you want].
And also what kind of changes you'd like to push forwards, or if you'd rather just work on fixing general maintenance issues that arise.

Cheers,
Paul

beanstalkd 1.4.2 with latest pheanstalk and no jobs locking up php?

When no more jobs are available to reserve(), the following code locks up after the last job is reserved:

class Fauxdaemon {
public static function run()
{
global $run, $sleep, $pheanstalk;

    echo "starting...\n";

    while ($run) {
        try {
            $job = $pheanstalk->watch('testtube')->ignore('default')->reserve();
            var_dump($job);
        } catch(Exception $e) {
            echo $e->getMessage();
        }

        echo '.';
    }

    echo "\nbye\n";

}

}

// Test jobs
$pheanstalk->useTube('testtube')->put('say hello');
$pheanstalk->useTube('testtube')->put('say goodbye');
$pheanstalk->useTube('testtube')->put('say hi there');

// Run
Fauxdaemon::run();

pause-tube command

Any plans to implement this in the near future? If certain consumers have the ability to handle multiple tubes then pause-tube is an elegant way to prioritize at a tube level. In other words this is the perfect solution if a certain tube gets backlogged and consumers waste time on tubes that aren't backlogged at all.

Trouble with phar portability

I know you just overhauled this, so first I'll reassure you that this predates that overhaul! I've found that build_phar.php builds phar archives that only work in the root directory of a git clone of the project itself.

henry@mbp:~/tmp/pheanstalk $ ./scripts/build_phar.php 
Phar configured readonly in php.ini; attempting to re-execute:
php -d phar.readonly=0 ./scripts/build_phar.php --ignore-readonly
- Deleting existing pheanstalk.phar
- Building pheanstalk.phar from /home/henry/tmp/pheanstalk/classes
- Generating Phar stub based on pheanstalk_init.php
- pheanstalk.phar built with 43 files.

# the newly-created archive works fine here:
henry@mbp:~/tmp/pheanstalk $ php pheanstalk.phar 

# but not if you move it anywhere else, like so:
henry@mbp:~/tmp/pheanstalk $ cp pheanstalk.phar .idea
henry@mbp:~/tmp/pheanstalk $ cd .idea
henry@mbp:~/tmp/pheanstalk/.idea $ php pheanstalk.phar 
PHP Warning:  require_once(/home/henry/tmp/pheanstalk/.idea/classes/Pheanstalk/ClassLoader.php): failed to open stream: No such file or directory in /home/henry/tmp/pheanstalk/.idea/pheanstalk.phar on line 16
PHP Fatal error:  require_once(): Failed opening required '/home/henry/tmp/pheanstalk/.idea/classes/Pheanstalk/ClassLoader.php' (include_path='.:/usr/share/php:/usr/share/pear') in /home/henry/tmp/pheanstalk/.idea/pheanstalk.phar on line 16

As you can see from the error message, it's because the phar contains a require once that attempts to load the Pheanstalk ClassLoader from outside the archive:

$ head -n 16 pheanstalk.phar | tail -n 1
require_once($pheanstalkClassRoot . '/Pheanstalk/ClassLoader.php');

I've never really had any exposure to Phar archive generation before so I can't say for sure what the fix for this ought to be. The workaround we went with for this problem was to simply stop using the Phar archive and instead install the regular class files themselves. I might have another look at fixing this myself at some point in the future if needs be.

Workers as separate processes

Does anyone have experience having the jobs in the queue performed by separate child processes initiated by something polling the queue?

Since some of our jobs may take a long time > 30 seconds, and we want to be able to support lots of consecutive jobs, it is not practical to have the daemon that is polling the queue to also perform the jobs.

My first instinct was to simply have one daemon polling the queue. If it finds a job, kick off a child process to actually run it. However, I don't see an easy way to poll the queue for jobs without actually reserving them. Using stats_tube() or any method besides reserve() creates an overwhelming number of connections to beanstalk. Reserve does not have this problem because it works with a socket. So, it would look something like this:

$q = new Pheanstalk('127.0.0.1:11300'); //Create a connection to beanstalk
$job = $q->watch('test')->reserve();
$q->release($job);
//Kick of a child process to grab the job again. And run it

It feels like this is a common use case (think of the way the apache daemon spawns children to handle requests). There must be a better solution to this problem but I'm at a loss for how to do it.

pda pheanstalk is NOT COMPATIBLE with OPCache

Laravel is a little bit slow..., and OPcache improves its performance by storing precompiled script bytecode in shared memory, thereby removing the need for PHP to load and parse scripts on each request.

BUT pda pheanstalk is NOT COMPATIBLE with OPCache....

SO could anyone please tell me how to solve the problem?~

NativeSocket's read() cannot read more all the bytes we want at once

I've encountered this problem on Windows XP, php 5.2.10 - jobs sized more than 4096 bytes and less than 8192 (due to previous bug fix) cannot be read - exception "Pheanstalk_Exception_ClientException: Expected 2 bytes of CRLF after 5000 bytes of data" is throwed.
I get this problem randomly on Debian Lenny, php 5.2.6 - exception is throwed really randomly, but always with job size less than 8192 bytes.

I've forked pheanstalk into http://github.com/SlNPacifist/pheanstalk, wrote a test for this bug (trying to put, peek and delete jobs with size incrementing from 1000 to 16000 with step 1000) (will commit soon).
Expecting getting rid of "read-at-once" optimisation to be the solution.

Create a new tag with composer

Hi there.
For composer, branches are considered to be unstable, and tags are stable.

The composer.json is only defined in the master branch. For composer, there is only one available version which is unstable.
Maybe you could create a new tag from master branch called 1.3.1 or 1.4.0.

Regards,
Thomas.

Pheanstalk doesn't work with Composer autoloader

Hi,

I tried to include Pheanstalk in a project using Composer.

{
    "name": "mnapoli/phpbeanstalkdadmin",
    "require": {
        "mnapoli/php-di": "dev-master",
        "zendframework/zendframework1": "1.12.*",
        "pda/pheanstalk": "dev-master"
    }
}

When I include Composer's autoload file (which normally can autoload libraries that it downloaded), I get an error when I try to use Pheanstalk:

Fatal error: Class 'Pheanstalk' not found

I think this is maybe because the Composer configuration is incomplete, the autoloader doesn't take into account Pheanstalk. Or maybe it's because the main class (Pheanstalk) is not in a namespace?

For example, here is the map of autoload namespaces that was generated:

return array(
    'Zend' => $vendorDir . '/zendframework/zendframework1/library/',
    'TestFixtures' => $vendorDir . '/mnapoli/php-di/tests/',
    'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
    'DI' => $vendorDir . '/mnapoli/php-di/src/',
);

All the other libraries are correctly taken into account to be autoloaded, but not Pheanstalk.

Delay any existing job.

Is that possible to delay any existing job? As per my research, there's no any direct facility to delay any existing job.

I think, to delay any existing job, you need to delete previous one and add new one with delay information. But, in that case I'm unable to find actual tube name from which job was fetched. That also unable to get from reserve command response.

Correct me if I'm wrong.

Thank...

Put and return Job Id

hi,
i'm using your library but i have an issue.
When i use put to put data inside my queue normally the return value has to be the job id but it's alway return 1 is that normal ?

Cheers
Bastien

statsJob Function: Call to undefined method Pheanstalk_Job::getJobId()

When I try to do $pheanstalk->statsJob($job) the following PHP error occurs:

Fatal error: Call to undefined method Pheanstalk_Job::getJobId() in /home/lib/pheanstalk/Pheanstalk/Command/StatsJobCommand.php on line 21

...in Line 21 $job->getId() should be called instead of $job->getJobId()

Any plan to support multiple servers?

Would be nice to give pheanstalk an array of server ip's and ports and have it just randomly (or even not so randomly) choose which one to send the job to. This would eliminate all of the developers who use pheanstalk from having to roll their own sharding solution.

Limited performance putting jobs

Hi,

I'd like to use pheanstalk as the client library for our application to access beanstalkd, mainly because of the poor implementation of the reserve methods in BeansTalk library that waste lots of cpu.

But I hit a performance problem when putting jobs into queues. It turned out to be really slow, taking 40 seconds to put only 1000 jobs on a loop.

I found out that the fgets() call inside the method getLine() from NativeSocket class was taking 0,04 seconds for each call. So I tried different things like using fread(), non-blocking socket, etc. but without success, the 0,04s delay still existed.

Then I found the double call to the write() method inside dispatchCommand() when there is some data to send after the command. I tried to join command and data in just one write() call, and voila! performance boosted to 1000 puts in just 0,100s on localhost and 0,180s over network! And everything looks like working as expected, tested on PHP 5.2.6 and 5.2.9.

I suspect this is something related to PHP not using the TCP_NODELAY flag for the socket connection, introducing a penalty when calling fwrite() two or more times without reading from the socket between this writes...

ivan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.