Symfony SncRedis Bundle exception handling if redis not available - php

I am using redis as a cache to help with application performance regarding data that has a high cost of generation. Currently we only have one redis instance running and I have observed that if redis is not available - then 500 error is being returned.
Given that I am caching - I would rather continue processing if redis is down and render that page with the data omitted.
I have tested using a basic php try - catch block - but it I have not been able to trap the exception.
public function redisAction()
{
try {
$redis = $this->container->get('snc_redis.default');
$val = $redis->get('foo:bar');
} catch (Exception $e ) {
$response = new Response('Oops ');
return $response;
}
....
}
Is there any other approaches I can take - I am also investigating the sncredis bundle to see if it can be addressed there.

Given you did not include use Exception on top of your class you will need to add a leading backslash ... otherwise PHP will try to catch Your\Current\Namespace\Exception which doesn't exist.
catch (\Exception $e ) {
// ...
}
But I'm not sure if redis throws an exception if the requested key does not exist (actually I don't think so).
You could use the exists() method to check if the key exists instead.
if ($redis->exists("foo:bar")) {
return new Response('Oops');
}

Related

How to manually catch error exception in Laravel

In my project i need to do a bulk import and data insertion in the database.
So, I needed to know that when a API request is failed. Here, the problem is that PHP unable to catch that exception because Laravel 5.6 would stop the execution while there is any kind of error.
I needed to stop laravel from automatically stop the execution and let php decide that if an API request failed then lets wait 5 second and try again.
To achieve this i have made a function inside a laravel controller.
private function fetchAPI($id) {
try {
$rawResult = file_get_contents('http://example.com/'.$id.'?key=5453');
} catch (Exception $e) {
sleep(5);
$this->fetchAPI($id);
}
return json_decode($rawResult, true);
}
The above method will utilize the try...catch block. But i have also implemented with a boolean check with no luck:
private function fetchAPI($id) {
$rawResult = file_get_contents('http://example.com/'.$id.'?key=5453');
if($rawResult === FALSE) {
sleep(5);
$this->fetchAPI($id);
} else {
return json_decode($rawResult, true);
}
}
In this scenario how i can re-try if API request failed from a Laravel controller method?
Use \Exception dans not Exception, because Exception is thought as YourCurrentFileNamespace\Exception.

PHP: Throw exception with multiple original/previous exceptions?

Consider the following code, where I want to throw a new exception to wrap "previous" exceptions that I just caught.
try {
doSomething();
}
catch (SomethingException $eSomething) {
try {
rollback();
}
catch (RollbackException $eRollback) {
throw new SomethingRollbackException('Copying failed, rollback failed.', null, $eSomething, $eRollback);
}
}
At some point I have two exceptions that I would want to pass in as "$previous", when constructing a new exception.
But natively, only one "previous exception" is supported.
Options I can think of so far:
Create my own exception class that accepts an additional "previous" exception. But then what? Store it as a private property? Or public? With an accessor? How would I make calling code to care about the extra information?
Of course I could just write to the log, and discard one or both of the exceptions. But this is not the point of this question.
Create my own exception class that accepts an additional "previous" exception. - Yes, let's say SomethingRollbackException
Store it as a private property? - Yes, but is matter of taste
With an accessor? - Yes, see above
How would I make calling code to care about the extra information? - something like this:
if ($exception instanceof SomethingRollbackException) {
// at this point you know $exception has 2 previous exceptions
}
or
try {
// ....
} catch(SomethingRollbackException $e) {
// at this point you know $exception has 2 previous exceptions
}

When running unit tests with laravel, how do you test your App::error() implementations?

I'm currently working on an open source personal project that provides a nice backend api for game developers. I'm in the early stages of development, but I plan to write tests as I go along, which is where I've hit a snag.
Through out the system when an error occurs such as incorrect api credentials or missing credentials, I throw a custom exception which stores a bit of extra data so that I can catch it and give a JSON encoded response.
The tests work fine for those thrown in my BaseController, but I also capture a few Laravel Exceptions so I can respond with my own, or at least, output JSON like below:
app/start/global.php
App::error(function(Exception $exception, $code) {
Log::error($exception);
});
App::missing(function(Exception $exception) {
return BaseController::error(
Config::get('response.method.code'),
Config::get('response.method.http'),
'Method not found'
);
});
App::error(function(Viper\Exception $exception) {
return BaseController::error(
$exception->getCode(),
$exception->getStatusCode(),
$exception->getMessage()
);
});
I'm using the try { } catch() { } approach as I need to check an extra value that isn't in the normal Exceptions.
public function testNoMethodGET() {
$config = Config::get('response.method');
try {
$this->call('GET', '/');
} catch(\Viper\Exception $e) {
$this->assertEquals($e->getCode(), $config['code']);
$this->assertEquals($e->getStatusCode(), $config['http']);
}
$this->fail('Exception not thrown');
}
This is all good and well, but I want to check a few things on the actual response, like for example, whether or not the json is valid, whether or not the response structure matches and whether or not the response values are correct.
If I set the return value of $this->call() to a variable, I'd be unable to access that variable within the catch block, so the question is this, how can I test the return value of $this->call() once the Exception has been caught?
According to Taylor Otwell:
"this can be solved by de-coupling your
test. You really want to test the handler and that the exception is
thrown totally separately anyways [sic] to isolate your tests. For
instance:
App::error(function(ErrorType $e)
{
App::make('ErrorTypeHandler')->handle($e);
});
Now you can write test cases for ErrorTypeHandler class separately
from the rest of your application. Then check that proper exceptions
are thrown by your app with #expectedException."
see How do you test your App::error implementations?
In your case, you already have isolated your error handler in BaseController::error(), so you can test the responses directly in separate unit tests, without the use of $this->call(). Instead, just call $response = BaseController::error() with the desired parameters and then inspect the response and apply relevant assertions.

Cannot catch exceptions in Module.php

I am having an issue where an exception is being thrown but not caught in Module.php. The code that throws the exception is wrapped in a try/catch. There's nothing really fancy going on so I am assuming ZF2 has a quirk and/or reason for not allowing exceptions to be caught here.
The code is as follows (simplified as necessary):
class Module
{
public function onBootstrap(MvcEvent $e)
{
// Get service manager, etc.
// Set up some environment stuff
try {
// exception is thrown
}
catch (\Exception $e) {
echo $e->get_message();
exit;
}
}
}
Why is the exception not being caught?
In an ideal world there would be a way to catch this exception here. But if that is not possible, or is too convoluted to be worth the effort, an alternative process to fetching this data (regardless of source) as early in the page loading process as possible would be appreciated.
meta
I know the code in Module.php is supposed to be lightweight. But we have to fetch some data immediately before any action is performed as it will contain data vital to those actions to be performed. This data is cached after the first visit so every other page load will avoid this overhead.
I also have Googled this but apparently no one else has either experienced this, asked about it, or documented it.
This code works just fine for me in a module class:
public function onBootstrap(MvcEvent $e)
{
try {
// exception is thrown
throw new \Exception('My exception here');
}
catch (\Exception $e) {
echo $e->getMessage();
exit;
}
}
It displays the exception message and exits.
One way to investigate what is happening is to use xdebug for step by step debugging.
Just add a breakpoint in your Module and see what ZF is doing.

How to bypass Laravel Exception handling

I have a method that checks if a user has valid Session info. This is supposed to throw an Exception, Guzzle\Http\Exception\BadResponseException but when I try to catch it :
catch (Guzzle\Http\Exception\BadResponseException $e)
{
return false;
}
return true
Laravel doesn't get to this code and immediately starts it's own error handling. And ideas on how to bypass Laravels own implementation and use my own Catch.
EDIT: I just found out Laravel uses the same Exception handler as Symfony, so I also added the Symfony2 tag.
EDIT 2:
I sort of fixed the issue by disabling Guzzle exceptions and checking the return header manually. It's a bit of a short cut but in this case, it does the job. Thanks for the responses!
Actually this exception can be catched in Laravel, you just have to respect (and understand) namespacing:
If you have
namespace App;
and you do
catch (Guzzle\Http\Exception\BadResponseException $e)
PHP understands that you are trying to
catch (\App\Guzzle\Http\Exception\BadResponseException $e)
So, for it to work you just need a root slash:
catch (\Guzzle\Http\Exception\BadResponseException $e)
And it will work.
By default, the app/start/global.php file contains an error handler for all exceptions. However, you may specify more handlers if needed. Handlers are called based on the type-hint of the Exception they handle. For example, you may create a handler that only handles your BadResponseException instances, like
App::error(function(Guzzle\Http\Exception\BadResponseException $exception)
{
// Handle the exception...
return Response::make('Error! ' . $exception->getCode());
});
Also, make sure you have a well defined (BadResponseException) class. Read more on Laravel Documentation.
Instead of your code
catch (Guzzle\Http\Exception\BadResponseException $e)
{
return false;
}
return true
use this solution
catch (\Exception $e)
{
return false;
}
return true
to catch all possible exceptions thrown by Guzzle.
If you explicitly want to catch a BadResponseException you can also prepend your exception's class namespace with '\'.
catch (\Guzzle\Http\Exception\BadResponseException $e)
{
return false;
}
return true

Categories