How to handle a Beanstalkd job that has an error - php

When my Beanstalkd job has an error, like "exception 'ErrorException' with message 'Notice: Undefined index: id in /var/www/mysite/app/libraries/lib.php line 248' in /var/www/mysite/app/libraries/lib.php:248, how should Beanstalkd knows that an error has occured and mark it as failed so it can be retried again?

Install a monitor for beanstalkd which can be useful when developing/testing your app. Some alternatives that uses PHP: http://mnapoli.github.io/phpBeanstalkdAdmin/ and https://github.com/ptrofimov/beanstalk_console
As for handling the errors, you could define your own error handler for beanstalkd jobs and in that handler decide if you want to:
bury (put the job aside for later inspection)
kick (put it back into the queue)
delete (remove it, if this is safe for your application)
EDIT - Did you manage to solve your problem?
The best way might be to use a try/catch around your jobs to catch the exceptions, and then bury it if the exception is raised at the worker. If the exception is raised at the producer it is probably never added into the queue so no need to bury() then, but use a monitor to make sure.
If you want to try to define an own error handler for your object I´ve done something similar before by setting up a custom error handler for your class. It might be a ugly hack by trying to get the pheanstalk (job) object through $errcontext - but might be something to try.. Here is some pseudo-code I quickly put together if you want to try it out (created a subclass to avoid put code into pheanstalk class):
class MyPheanstalk extends Pheanstalk {
function __construct() {
//register your custom error_handler for objects of this class
set_error_handler(array($this, 'myPheanstalk_error_handler'));
//call parent constructor
parent::__construct();
}
function myPheanstalk_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
// get the current job that failed
foreach($errcontext as $val) //print_r($errcontext) to find info on the object(job) you are looking for
{
if(is_object($val)) {
if(get_class($val) == 'Pheanstalk') { //and replace with correct class here
//optionally check errstr to decide if you want to delete() or kick() instead of bury()
$this->bury($val);
}
}
}
}
}

Its your script that has the error, not beanstalkd.
try {
//your code from Line 248 here
} catch (ErrorException $e) { //this section catches the error.
//you can print the error
echo 'An error occurred'. $e->getMessage();
//or do something else like try reporting the ID is bad.
if (!isset($id)) {
echo 'The id was not set!';
}
} //end of try/catch

Related

Function that checks if function executes successfully, otherwise exception. Possible in PHP?

I need some function that will accept a function as the parameter and will run it in try {} catch (Exception $e) {}. If it runs successfully, do nothing, otherwise, throw new Exception. That's something like function-checker, which checks functions if they ran successfully. Anybody can help me or give advice?
Thanks for any replies.
The function should work like that:
function itwillfail () {
echo 10 / 0;
}
check("itwillfail");
Output: Caught exception: Custom exception text here, because it has been thrown as custom.
("check" is that function I need)
What I tried:
function check($func) {
try {
call_user_func($func);
} catch (Exception $e) {
throw new Exception("Custom text here.");
}
}
EDIT: More explained: I need to create function, which do the same as "try" and a lot of different "catch"es for different types of exceptions.
Summarizing your question:
You want a way to call a custom function from a string variable (which you have already figured out that would be via call_user_func($var);.
You then want that function to throw a custom exception error
Confused
What is not clear is the reason you would opt to not define your error handler using the set_error_handler function which would effectively do what your asking and set a switch statement to output different messages based on the error generated.
Example
The following example is not using a call_user_func but it effectively allows you to write how the error will be handled
<?php
function myerror($error_no, $error_msg) {
echo "Error: [$error_no] $error_msg ";
echo "\n Now Script will end";
die();
}
// Setting set_error_handler
set_error_handler("myerror");
$a = 10;
$b = 0;
// Force the error
echo($a / $b);
?>
Not every function throws an exception when they fail. Many functions, especially ones that have been around for a long time, simply trigger PHP errors rather than exceptions.
To handle those, you would use a custom error handler:
https://www.php.net/manual/en/function.set-error-handler.php
So you could set up a custom error handler that would intercept those kinds of failures and throw them as exceptions. The whole point of that function is to do what you're trying to do - handle errors in a custom way.

Handling PHP exceptions the correct way

I'm developing my own PHP framework and my code althought is working like it should, it's getting bigger and bigger; that of course leads to multiple ways for my framework to break, so I have decided it is time to implement Exception handling like any other PHP framework does, that 'nice' error view that tells you what might went wrong.
I have done my research and kind of understand how the Extension PHP default class works, I know that I'm able to extend this class and customize the error messages.
I also know that to trigger an Exception you gotta throw it and catch it with a "try/catch" statement, somethin like this...
class MyCustomException extends \Exception()
{
// My stuff
}
public function dontBeZero($number)
{
if ($number == 0) {
throw new MyCustomException('You gave me zero!!');
}
}
try {
dontBeZero(0);
} catch (MyCustomException $e) {
echo '<pre>';
$e->getMessage();
echo '</pre>';
}
I understand that, but my real question is: How does this popular frameworks such as Laravel, Symfony, etc manage to throw you a pretty message showing you what the error was, where do they keep all the logic that verifies whether it should or should not throw an exception, and most importantly where did they catch them?.
Most frameworks show these errors via a custom error handler. A popular one used by laravel is whoops.
You just need to register it as a custom handler, and you'll see the pretty error pages:
$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
Keep in mind, you should disable these on production (so that your stack traces/code isn't exposed).
See the two functions set_error_handler and set_exception_handler. These functions allow you to register a callback function which is called when an error or exception occurs.
These callback functions are called by the Php runtime and provided with error details as arguments. The error details include error line number, stack trace, file name and more. The callback function can then format and display this information

When an exception is thrown and bubble up where a solution is found, how can we send the control back to where the exception was thrown?

For concreteness, I present some code, in which what I want, I know, is not possible. I am looking for another way to get the same.
<?php
error_reporting(E_ALL | E_STRICT);
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
// When $errno is a notice, we would like a way for the execution to continue here. Since it is only a notice, eventually it could go back to where the notice was triggered.
}
set_error_handler("exception_error_handler");
Class TopLevelManagement {
private $genericInfo = "Very important to add in notices";
function highleveljob() {
try{
// In practice, the following statements could occur below in the execution tree, after a few other function calls.
$specific = new SpecificAndEncapsulated();
$specific->specificjob();
}
catch (ErrorException $e) {
$message = $e->getMessage() . $this->genericInfo;
mail($admin_email, "Consider the generic info and recover from this situation", $message);
// Here we would like the execution to continue where the exception was thrown. In the real world, this would be like "thank you error handler for SpecificAndEncapsulated::specificjob, we have taken care of the issue with the help of our larger perspective.".
}
}
}
Class SpecificAndEncapsulated {
function specificjob() {
// Some processing
if($unexpected == true) trigger_error('Here is how little I know, as I should', E_USER_NOTICE);
// Continue as expected after a notice.
}
}
?>
Of course, one solution is to pass $genericInfo as a parameter or as a global variable to SpecificAndEncapsulated::justdomyjob and let the error_handler take care of the issue without bubbling up any exception. However, this solution is not natural. There are other ways to systematically pass the variable $genericInfo to SpecificAndEncapsulated, but the issue will be the same. There should be no need to systematically pass the $genericInfo value, because it is not something that should concern SpecificAndEncapsulated, not even when an exception occurs, even less systematically at every call. A communication back to the issuer of the exception saying "thanks, now continue", after a notice has been managed at an higher level, is natural. Is there a support for this type of E_NOTICE or E_USER_NOTICE management?
Exceptions, by design, are errors after which normal execution cannot continue.
In the real world, it would go like this: a police officer (third party) calls a trucking company dispatcher (the top-level code) and says, "one of your trucks exploded in a ball of fire and the driver is in the hospital" (the job), and the dispatcher says "Noted. I expect the payload to arrive on schedule."
You have to catch exceptions inside the job if you want to continue the job. One viable approach is to pass an error handler function or a delegate object into the job.
PHP 5 has an exception model similar to that of other programming languages. An exception can be thrown, and caught ("catched") within PHP. Code may be surrounded in a try block, to facilitate the catching of potential exceptions. Each try must have at least one corresponding catch block. Multiple catch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within the try block, or when a catch matching the thrown exception's class is not present) will continue after that last catch block defined in sequence. Exceptions can be thrown (or re-thrown) within a catch block.
When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block. If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has been defined with set_exception_handler().
In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
The thrown object must be an instance of the Exception class or a subclass of Exception. Trying to throw an object that is not will result in a PHP Fatal Error.

Is it bad programming to just throw exceptions while not in a try catch block?

I'm currently working in PHP. I'm working on a error system for my CMS I'm building (for the fun of it). For fatal errors in my system (not in the php compiler) I created a FatalException class that extends the built in Exception class. Since these types of errors kinda halt the system anyway, I threw in a exit into the __construct.
class FatalException extends Exception{
public function __construct($message) {
exit("<h1 style='color:red;' >FATAL ERROR: $message </h1>");
}
}
So in my code I'll check something like the connection to the database and if it can't then I'll just throw a FatalException("Can't connect to database: $database_error_message"). It won't be in a try/catch block.
When I run the code and can't connect to the database, for example, all I see on the screen is a sentence in big red letters. So it works just fine, but is this bad practice/coding?
EDIT:
Actually in truth it didn't start out this way. I was originally logging the error and then exiting in the catch area, but then I thought, if all fatal errors are going to exit anyway then just put in the in constructor. Then I noticed it wasn't actually getting to the catch area it was exiting. So putting the statement in a try/catch block was kind of a moot point. Which lead to the question.
If you're going to exit() unconditionally in a constructor, there's not really much point making it a constructor, let alone making the class an Exception. You could more simply (and honestly) have a static function called Fatal::Die($message).
The point of exceptions is that they describe what the error is (by having different classes for different exceptions) and can be caught - even if only to log them to a file and bail out of the program.
What if a particular page of your site could actually cope fine without a database connection (just missing the "latest news" or something)? Then it could catch( Database_Exception $e ) and continue, while the rest of your site just falls straight into the last-ditch "oh no something went wrong" message.
A message in big red letters is also not a great error-handling mechanism for anything that someone other than you will use - either they end up seeing technical details of the error when you're not looking, or you don't know what went wrong because you hid that error.
Even you wrap exit() into a member function of an exception, you are not using the exception here for error handling, but just the exit() - the exception is never thrown, PHP comes to halt before that happens.
So it works just fine, but is this bad practice/coding?
Yes, it is bad practice. It also works just fine if you would have created yourself a function:
function error_exit($message) {
exit("<h1 style='color:red;' >FATAL ERROR: $message </h1>");
}
Instead think about whether you want to use Excpetions or you want to exit().
This is a bad idea imho. An exception needs to be caught in order to function properly. You may however create a method like ->error( $index ); that attaches to every object you make.
From there you can route the error to a specific class with a try / catch block to properly handle the errors.
class TestClass
{
public function error( $index )
{
try
{
// Convert index to exception and throw it.
}
catch ( Exception $e )
{
// Handle the error
}
}
}
$a = new TestClass();
$a->error( 1000 );
Do note that this will not work for exceptions that php throws, you'll need to catch these seperately or work with execution hubs.

Why and how would you use Exceptions in this sample PHP code?

I've been wondering why would I use Exceptions in my PHP. Let's take a look at a simple example:
class Worker
{
public function goToWork()
{
return $isInThatMood ?
// Okay, I'll do it.
true :
// In your dreams...
false;
}
}
$worker = new Worker;
if (!$worker->goToWork())
{
if (date('l',time()) == 'Sunday')
echo "Fine, you don't have to work on Sundays...";
else
echo "Get your a** back to work!";
}
else
echo "Good.";
Is there a reason for me to use Exceptions for that kind of code? Why? How would the code be built?
And what about code that may produce errors:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
return file_get_contents($file);
}
}
Why would I use Exceptions in the above case? I have a feeling that Exceptions help you to recognize the type of the problem, which occured, true?
So, am I using Exceptions appropriately in this code:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return throw new Exception("File not found.",123);
try
{
$contents = file_get_contents($file);
}
catch (Exception $e)
{
return $e;
}
return $contents;
}
}
Or is that poor? Now the underlying code can do this:
$fo = new FileOutputter;
try
{
$fo->outputFile("File.extension");
}
catch (Exception $e)
{
// Something happened, we could either display the error/problem directly
echo $e->getMessage();
// Or use the info to make alternative execution flows
if ($e->getCode() == 123) // The one we specified earlier
// Do something else now, create "an exception"
}
Or am I completely lost here?
When should I use an exception?
You use an exception to indicate an exceptional condition; that is, something which prevents a method from fulfilling its contract, and which shouldn't have occurred at that level.
For example, you might have a method, Record::save(), which saves changes to a record into a database. If, for some reason, this can't be done (e.g. a database error occurs, or a data constraint is broken), then you could throw an exception to indicate failure.
How do I create custom exceptions?
Exceptions are usually named such that they indicate the nature of the error, for example, DatabaseException. You can subclass Exception to create custom-named exceptions in this manner, e.g.
class DatabaseException extends Exception {}
(Of course, you could take advantage of inheritance to give this exception some additional diagnostic information, such as connection details or a database error code, for example.)
When shouldn't I use an exception?
Consider a further example; a method which checks for file existence. This should probably not throw an exception if the file doesn't exist, since the purpose of the method was to perform said check. However, a method which opens a file and performs some processing could throw an exception, since the file was expected to exist, etc.
Initially, it's not always clear when something is and isn't exceptional. Like most things, experience will teach you, over time, when you should and shouldn't throw an exception.
Why use exceptions instead of returning special error codes, etc?
The useful thing about exceptions is that they immediately leap out of the current method and head up the call stack until they're caught and handled, which means you can move error-handling logic higher up, although ideally, not too high.
By using a clear mechanism to deal with failure cases, you automatically kick off the error handling code when something bad happens, which means you can avoid dealing with all sorts of magic sentinel values which have to be checked, or worse, a global error flag to distinguish between a bunch of different possibilities.
I'm not a PHP programmer, but this looks similar to C#.
Typically you'd want to throw errors if it is a point of no return. Then you would be able to log something to show that the impossible happened.
If you can tell that the file doesn't exist then you could just say that. No real need in my mind to also throw an exception.
Now if the file was found and you are processing it, and say only half the file was uploaded and you had no way of telling that without an exception, then it'd be nice to have around.
I would say it's a good design practice to avoid the catch all exceptions "catch (Exception $e)" and design by contract instead, just like you seem to be doing in the prior example. I would at first be more specific with the type of exception being thrown and then work from there if needed. Otherwise, stay away from the try->catch and exceptions.
In no way can you assume that a file exists just because you called file_exists()! The function file_exists doesn't open the file, so the file can potentially be deleted or renamed or moved at any time!
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
///<--- file may be deleted right here without you knowing it
return file_get_contents($file);//<-- then this will throw an error
//if you don't catch it, you're program may halt.
}
}
I believe this it better:
class FileOutputter
{
public function outputFile($file)
{
try{
if (!file_exists($file))
return false;
return file_get_contents($file);
}catch(Exception e){
check_what_went_wrong_and_go_to_plan_B();
}
}
}
(Edit: And it's probably even better to actually try to open the file from the beginning. If you succeed then you have a 'lock' on the file and it won't just disappear. If not, then catch the exception and see what went wrong.
Then again, you might feel that this level of reduncancy is just silly. In that case I don't think you need to worry about try/catch at all :)
Just a note really, your code for file outputter is invalid, since file_get_contents($file)
does not throw an exception. It will however raise a warning if the file doesn't exist, or can't be accessed for some reason. Additionally, you are returning an exception from outputFile, when you should probably be just letting the error propagate up the call stack.
However, you can register the error handler in php to throw exceptions when an error occurs:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
That way, any standard function calls that cause an error will throw an exception.
So, I would change FileOutputter to this (with that snippet above added):
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
throw new Exception("File not found.",123);
return file_get_contents($file);
}
}
The calling code is then basically the same.
Basically rule is not to return an Exception when an error occurs - you can catch it if you want, and throw a custom exception, but let the exception go up the call stack until you want to use it.

Categories